Unix环境,产生单实例进程方案

来源:互联网 发布:java final static变量 编辑:程序博客网 时间:2024/06/03 22:26

    在一些情况下,一个进程只能产生一个实例来执行。Unix环境,提供了文件-记录锁(file- and record-locking)机制,提供了事项单实例进程的基本解决方案。

    假如,一个进程在开始运行时,生成了一个文件,并且,对整个文件上锁,并且,只有一个这样的写锁允许生成。

    如果,后续的进程要试图产生写锁,会导致失败。这暗示了,前面已经有实例运行了

    下面一个判断是否有实例运行的方法。每个实例,都会试图生成一个文件(/var/run/daemon.pid).如果文件已经锁上了,lockfile方法失败,函数返回1,表示进程已经运行了。如果没有实例运行,lockfile方法成功,接着:清空文件,写入进程id,最后函数返回0.

    下面为一个实现的程序:

[cpp] view plaincopy
  1. #include <unistd.h>  
  2. #include <stdio.h>  
  3. #include <stdlib.h>  
  4. #include <fcntl.h>  
  5. #include <syslog.h>  
  6. #include <string.h>  
  7. #include <errno.h>  
  8. #include <sys/stat.h>  
  9. #define LOCKFILE "/var/run/daemon.pid"  
  10. #define LOCKMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)  
  11. int already_running(void);  
  12. int lockfile(int );  
  13. int main(int argc,char * argv[])  
  14. {  
  15.     int val = already_running();  
  16.     if(val == 0)  
  17.     {  
  18.         printf("sart to running.../n");  
  19.     }  
  20.     else  
  21.     {  
  22.         printf("alredy running.../n");  
  23.         exit(0);  
  24.     }  
  25.     while(1)  
  26.     {  
  27.         sleep(3);  
  28.         printf(".../n");  
  29.     }  
  30.     return 0;  
  31. }  
  32. int already_running(void)  
  33. {  
  34.     int fd;  
  35.     char buf[16];  
  36.     fd = open(LOCKFILE,O_RDWR|O_CREAT, LOCKMODE);  
  37.     if(fd < 0)  
  38.     {  
  39.         syslog(LOG_ERR, "can't open %s: %s", LOCKFILE, strerror(errno));  
  40.         exit(1);  
  41.     }  
  42.     if(lockfile(fd) < 0)  
  43.     {  
  44.         if (errno == EACCES || errno == EAGAIN)  
  45.         {  
  46.             close(fd);  
  47.             return 1;  
  48.         }  
  49.         syslog(LOG_ERR,"can't lock %s: %s", LOCKFILE, strerror(errno));  
  50.         exit(1);  
  51.     }  
  52.     ftruncate(fd,0);  
  53.     sprintf(buf,"%ld",(long)getpid());  
  54.     write(fd,buf,strlen(buf) + 1);  
  55.     return 0;  
  56. }  
  57. int lockfile(int fd)  
  58. {  
  59.     struct flock fl;  
  60.     fl.l_type = F_WRLCK;  
  61.     fl.l_start = 0;  
  62.     fl.l_whence = SEEK_SET;  
  63.     fl.l_len = 0;  
  64.     return(fcntl(fd, F_SETLK, &fl));  
  65. }  

     

   在Unix/Linux环境下,写入文件时。如果,在open函数的读写模式,只提供了,读写,如果不存在”生成“这些模式时。

    如果源文件存在,以非追加的方式写入数据时,当后续的数据长度大于源文件已有的数据时,后续的文件覆盖以前的数据。

    如果后续的数据长度小于源文件以后的数据长度时,只是覆盖了后续写入的数据长度。这时,文件的数据是两者的混合,这不是我们想要的。

    所以为了数据的正确性,在以非追加(append)方式写入数据时,首先要清空,要写入的文件。

   以下为一个例子:
[cpp] view plaincopy
  1. #include<stdio.h>  
  2. #include<stdlib.h>  
  3. #include<fcntl.h>  
  4. int main(int argc ,char * argv[])  
  5. {     
  6.     int val = 0;  
  7.     int fd = 0;  
  8.     char* fpath = "./test.txt";  
  9.     char buffer[] = "Hi i am harry.";  
  10.     char buffer1 []= "liyachao.";  
  11.     /*open the file with write/read and create module*/  
  12.     fd = open(fpath,O_RDWR|O_CREAT);  
  13.     /*truncate the exiting file's size to zero,meanning empty the exit file.*/  
  14.     ftruncate(fd,0);  
  15.     val = write(fd,buffer,strlen(buffer));  
  16.     printf("wirte %d bytes.",val);  
  17.      
  18.     return 0;  
  19. }