歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux基礎 >> Linux技術 >> linux下的單實例進程

linux下的單實例進程

日期:2017/3/3 13:55:26   编辑:Linux技術

最近項目中的一個計數程序,因為會計數,所以只能有一個進程在運行,否則計數速度會加快,而剛好又是一個守護進程。Steven的《unix環境高級編程》的守護進程中就有講,單實例進程。

這種監控有很多,如果放在兩年前,我可能會用shell腳本,但這真的是一個又懶又笨又漏洞百出的方法了。寫下我知道的都有什麼方法:

1 shell使用ps命令來判斷

2 信號量/共享內存

3 創建文件寫入0或1作為啟動/關閉標志,異常退出

4 創建文件,加鎖(建議性鎖),daemon進程寫pid文件,/var/run/xx.pid

首先,方法1, 進程名字改變無法監控,又外加了腳本,實在多余

方法2, 這個可以嘗試,守護進程用信號量不知道會不會有什麼問題,有時間的話可以研究下。

方法3,呃,也是個笨方法了,程序異常退出等無法及時改文件的話就有問題。

方法4,我采用的方法了,感覺很可靠,程序退出釋放鎖,是不是很靠譜呢。

先解釋下這個函數的機制,在”/var/run/”目錄下建立一個文件,一般是以進程名字命名。裡面只寫入進程號。注意,這個目錄是默認守護進程會寫的目錄,所以建議大家遵循這個規則。(關於守護進程默認遵循的規則,比如自動重啟,作為服務啟動關閉等,參考該書即可)

該文件加建議性寫鎖,進程在運行期間一直持有該鎖,不釋放,而是在進程退出後自動釋放。所以獲取該鎖失敗就說明進程已經在運行。直接退出。

函數中寫日志接口是項目中的日志模塊,可以直接用linux系統中的syslog日志服務進行監控。

函數中加鎖的函數采用fcntl函數,可以參考該書中對fcntl的封裝,用起來非常方便。文章最後附上該封裝函數。

如果是守護進程,該函數需要在daemon後調用,因為daemon函數會對文件描述符做操作。

如果不是守護進程,直接調用就OK了

#define LOCKFILE "/var/run/xxxx.pid"

static int already_running(void)

{

int fd;

char buf[32];

fd = open(LOCKFILE, O_RDWR|O_CREAT, 0644);

if (fd < 0) {

write_log(IRILOG_ERR, "Iridium license daemon start fail!");

exit(1);

}

/* 加建議性寫鎖 */

if (write_lock(fd, 0, SEEK_SET, 0) < 0) {

close(fd);

exit(1);

}

ftruncate(fd, 0); /* 文件清零,因為只寫一次pid號

*/

snprintf(buf, 32, "%ld", (long)getpid());

write(fd, buf, strlen(buf)+1);

return(0);

}

=============== fcntl函數封裝 =============================

頭文件:

#ifndef WRAPFCNTL_H

#define WRAPFCNTL_H

#include <stdio.h>

#include <string.h>

#include <sys/types.h> /* about files */

#include <sys/stat.h>

#include <sys/file.h>

#include <fcntl.h>

#include <unistd.h>

#include <pthread.h>

/* fcntl函數的包裝,帶w表示阻塞調用*/

#define read_lock(fd, offset, whence, len) lock_reg((fd), F_SETLK, F_RDLCK, (offset), (whence), (len))

#define readw_lock(fd, offset, whence, len) lock_reg((fd), F_SETLKW, F_RDLCK, (offset), (whence), (len))

#define write_lock(fd, offset, whence, len) lock_reg((fd), F_SETLK, F_WRLCK, (offset), (whence), (len))

#define writew_lock(fd, offset, whence, len) lock_reg((fd), F_SETLKW, F_WRLCK, (offset), (whence), (len))

#define un_lock(fd, offset, whence, len) lock_reg((fd), F_SETLK, F_UNLCK, (offset), (whence), (len))

int lock_reg(int fd, int cmd, int type, off_t offset, int whence, off_t len);

#endif

.c文件

#include "wrapfcntl.h"

int lock_reg(int fd, int cmd, int type, off_t offset, int whence, off_t len)

{

struct flock lock;

lock.l_type = type; /* F_RDLCK, F_WRLCK, F_UNLCK */

lock.l_start = offset; /* byte offset, relative to l_whence */

lock.l_whence = whence; /* SEEK_SET, SEEK_CUR, SEEK_END */

lock.l_len = len; /* #bytes (0 means to EOF) */

return (fcntl(fd, cmd, &lock));

}

Copyright © Linux教程網 All Rights Reserved