程序在啟動時將pid寫入文件,當程序再次啟動時會進行檢測,避免啟動多個實例。
util-pidfile.h文件
1 #ifndef __UTIL_PID_H__ 2 #define __UTIL_PID_H__ 3 4 int PidfileCreate(const char *); 5 void PidfileRemove(const char *); 6 int PidfileTestRunning(const char *pid_filename); 7 8 #endif /* __UTIL_PID_H__ */
util-pidfile.c文件
1 #include <stdio.h> 2 #include <inttypes.h> // PRIuMAX 3 #include <errno.h> // errno 4 #include <string.h> // strerror 5 6 #include <sys/types.h> 7 #include <sys/stat.h> 8 #include <fcntl.h> 9 #include <unistd.h> // getpid 10 #include <signal.h> // kill 11 12 #include "util-debug.h" 13 #include "util-pidfile.h" 14 15 /** 16 * \brief Write a pid file (used at the startup) 17 * This commonly needed by the init scripts 18 * 19 * \param pointer to the name of the pid file to write (optarg) 20 * 21 * \retval 0 if succes 22 * \retval -1 on failure 23 */ 24 int PidfileCreate(const char *pidfile) 25 { 26 int pidfd = 0; 27 char val[16]; 28 29 int len = snprintf(val, sizeof(val), "%"PRIuMAX"\n", (uintmax_t)getpid()); 30 if (len <= 0) { 31 LogError("Pid error (%s)", strerror(errno)); 32 return(-1); 33 } 34 35 pidfd = open(pidfile, O_CREAT | O_TRUNC | O_NOFOLLOW | O_WRONLY, 0644); 36 if (pidfd < 0) { 37 LogError("unable to set pidfile '%s': %s", 38 pidfile, 39 strerror(errno)); 40 return(-1); 41 } 42 43 ssize_t r = write(pidfd, val, (unsigned int)len); 44 if (r == -1) { 45 LogError("unable to write pidfile: %s", strerror(errno)); 46 close(pidfd); 47 return(-1); 48 } else if ((size_t)r != len) { 49 LogError("unable to write pidfile: wrote" 50 " %"PRIdMAX" of %"PRIuMAX" bytes.", (intmax_t)r, (uintmax_t)len); 51 close(pidfd); 52 return(-1); 53 } 54 55 close(pidfd); 56 return(0); 57 } 58 59 /** 60 * \brief Remove the pid file (used at the startup) 61 * 62 * \param pointer to the name of the pid file to write (optarg) 63 */ 64 void PidfileRemove(const char *pid_filename) 65 { 66 if (pid_filename != NULL) { 67 /* we ignore the result, the user may have removed the file already. */ 68 (void)unlink(pid_filename); 69 } 70 } 71 72 /** 73 * \brief Check a pid file (used at the startup) 74 * This commonly needed by the init scripts 75 * 76 * \param pointer to the name of the pid file to write (optarg) 77 * 78 * \retval 0 if succes 79 * \retval -1 on failure 80 */ 81 int PidfileTestRunning(const char *pid_filename) 82 { 83 if (access(pid_filename, F_OK) == 0) { 84 /* Check if the existing process is still alive. */ 85 pid_t pidv; 86 FILE *pf; 87 88 pf = fopen(pid_filename, "r"); 89 if (pf == NULL) { 90 LogError("pid file '%s' exists and can not be read. Aborting!", 91 pid_filename); 92 return -1; 93 } 94 95 if (fscanf(pf, "%d", &pidv) == 1 && kill(pidv, 0) == 0) { 96 fclose(pf); 97 LogError("pid file '%s' exists. Is program already running? Aborting!", 98 pid_filename); 99 return -1; 100 } 101 102 fclose(pf); 103 } 104 return 0; 105 }
util-debug.h日志打印(主要是為了方便以后使用其他打印接口,就不用再修改util-pidfile.c文件了)
1 #ifndef __UTIL_DEBUG_H__ 2 #define __UTIL_DEBUG_H__ 3 4 #ifndef LOG_PRINT 5 #define LOG_MAX_LOG_MSG_LEN 2048 6 #define Log(x, file, func, line, ...) \ 7 do { \ 8 char _log_msg[LOG_MAX_LOG_MSG_LEN]; \ 9 snprintf(_log_msg, LOG_MAX_LOG_MSG_LEN, __VA_ARGS__); \ 10 fprintf(stdout, "<%s> %s\n", x, _log_msg); \ 11 } while(0) 12 13 #define LogError(...) Log("ERROR", \ 14 __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__) 15 16 #define LogWarning(...) Log("WARNING", \ 17 __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__) 18 19 #define LogInfo(...) Log("INFO", \ 20 __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__) 21 22 #define LogDebug(...) Log("DEBUG", \ 23 __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__) 24 25 #define FatalError(...) do { \ 26 LogError(__VA_ARGS__); \ 27 exit(EXIT_FAILURE); \ 28 } while(0) 29 #endif 30 31 32 #endif //__UTIL_DEBUG_H__
main.c文件
1 #include <stdio.h> 2 #include <unistd.h> 3 4 #include "util-pidfile.h" 5 6 7 int main() 8 { 9 int result = 0; 10 11 const char *pidfile = "/var/run/test_pid01.pid"; 12 13 if (PidfileTestRunning(pidfile) != 0) 14 return -1; 15 16 PidfileCreate(pidfile); 17 18 while (1){ 19 sleep(1); 20 } 21 22 PidfileRemove(pidfile); 23 return 0; 24 }
編譯完成后運行該程序,然后再啟動一個終端,再次運行這個程序的時候就會打印程序已運行並退出。
<ERROR> pid file '/var/run/test_pid01.pid' exists. Is program already running? Aborting!