判断程序实例是否已经运行的N种方法

来源:互联网 发布:godaddy域名优惠 编辑:程序博客网 时间:2024/05/17 22:02

转自:http://socol.iteye.com/blog/687728


1.  在创建的文件中写入进程的ID,如果机器非正常退出,重启后先读取这个文件,得到进程ID,再根据ID判定进程是否正在运行,如果不是,则把文件删除掉。这样就不会发生不删除文件,程序运行不起来的问题了。

 

2.  打开一个文件,然后锁定,新运行的程序会试图再次锁定该文件,但是因为已经被锁定,所以会返回错误信息。据此就可以判断是否有程序已经运行。设置FD_CLOEXEC后,只要程序终止,都可以再次锁定。
通常精灵进程都使用这种方法,比如apache等等,而且默认都会在/var/run目录

Qt代码  收藏代码
  1. #include <stdlib.h>  
  2. #include <stdio.h>  
  3. #include <fcntl.h>  
  4. #include <signal.h>  
  5. #include <unistd.h>  
  6. #include <sys/stat.h>  
  7. #include <errno.h>  
  8.   
  9. #include <QtCore/QCoreApplication>  
  10. #include <QDebug>  
  11.   
  12. #define PIDFILE "/var/run/my.pid"  
  13. #define write_lock(fd,offset,whence,len) lock_reg(fd,F_SETLK,F_WRLCK,offset,whence,len)  
  14. #define FILE_MODE (S_IRWXU|S_IRWXG|S_IRWXO)  
  15.   
  16. int lock_reg (int fd, int cmd, int type, off_t offset, int whence, off_t len)  
  17. {  
  18.     struct flock lock;  
  19.   
  20.     lock.l_type = type;  
  21.     lock.l_start = offset;  
  22.     lock.l_whence = whence;  
  23.     lock.l_len = len;  
  24.   
  25.     int ret = fcntl(fd, cmd, &lock);  
  26.     return ret;  
  27. }  
  28.   
  29. bool isSingleton()  
  30. {  
  31.     int fd,val;  
  32.     char buf[10];  
  33.   
  34.     if ((fd = open(PIDFILE, O_WRONLY|O_CREAT, FILE_MODE)) < 0) {  
  35.         qDebug() << "daemon need run by root. open" << PIDFILE << "error.";  
  36.         return false;  
  37.     }  
  38.   
  39.     if(write_lock(fd, 0, SEEK_SET, 0) < 0)  
  40.     {  
  41.         if (errno == EACCES || errno == EAGAIN)  
  42.             qDebug() << "daemon has been in running!";  
  43.         else  
  44.             qDebug() << "daemon other error.";  
  45.         return false;  
  46.     }  
  47.   
  48.     if (ftruncate(fd, 0) < 0) {  
  49.         qDebug() << "ftruncate error.";  
  50.         return false;  
  51.     }  
  52.   
  53.     sprintf(buf,"%d\n",getpid());  
  54.     if (write(fd, buf, strlen(buf)) != strlen(buf)) {  
  55.         qDebug() << "pid write error.";  
  56.         return false;  
  57.     }  
  58.   
  59.     // close file descriptor  
  60.     if ((val = fcntl(fd, F_GETFD, 0)) < 0) {  
  61.         qDebug() << "fcntl F_GETFD error.";  
  62.         return false;  
  63.     }  
  64.     val |= FD_CLOEXEC;  
  65.     if (fcntl(fd, F_SETFD, val) < 0) {  
  66.         qDebug() << "fcntl F_SETFD error.";  
  67.         return false;  
  68.     }  
  69.   
  70.     return true;  
  71. }  
  72.   
  73. void initDaemon(void)  
  74. {  
  75.     pid_t pid, sid;  
  76.     if((pid = fork()) < 0)  
  77.         return;  
  78.     else if(pid != 0)  
  79.         exit(0); /* parent exit */  
  80.     /* child continues */  
  81.     sid = setsid(); /* become session leader */  
  82.     if (sid < 0) {  
  83.         exit(-1);  
  84.     }  
  85.     /* change working directory */  
  86.     if ((chdir("/")) < 0) {  
  87.         exit(-1);  
  88.     }  
  89.     umask(0); /* clear file mode creation mask */  
  90. #if 0  
  91.     close(0); /* close stdin */  
  92.     close(1); /* close stdout */  
  93.     close(2); /* close stderr */  
  94. #endif  
  95. }  
  96.   
  97. int main(int argc, char *argv[])  
  98. {  
  99.     initDaemon();  
  100.   
  101.     if (!isSingleton())  
  102.         return 0;  
  103.     QCoreApplication a(argc, argv);  
  104.     return a.exec();  
  105. }  
 

 

3. 遍历/proc目录下的进程信息,如果应用程序对应的进程存在,则让认为应用程序已经在运行。然后强制关闭该应用程序,用新的命令行参数重新运行 它。这样做的优点是实现简单,到达了我们预期的目标。缺点是强制kill第一个运行实例太野蛮,可能会造成数据丢失,另外创建新进程的开销会让用户感觉反 应迟钝。

C代码  收藏代码
  1. /* 
  2.  * getpid shell: pidof XXX 
  3.  * Returns the executable name for given pid. 
  4.  */  
  5. static gchar *  
  6. pid_to_binary_name (gint pid)  
  7. {  
  8.   gchar * cmd_f;  
  9.   FILE  * fcmd;  
  10.   
  11.   if (pid <= 0)  
  12.     return NULL;  
  13.   
  14.   cmd_f = g_strdup_printf ("/proc/%d/cmdline", pid);  
  15.   fcmd  = fopen (cmd_f, "r");  
  16.   
  17.   g_free (cmd_f);  
  18.   
  19.   if (fcmd)  
  20.     {  
  21.       gchar buf[256];  
  22.       if (fgets (buf, sizeof (buf), fcmd))  
  23.         {  
  24.           /* 
  25.            * 0-terminate at first whitespace. 
  26.            */  
  27.           gchar *n = &buf[0];  
  28.           while ((n < &buf[0] + sizeof(buf) - 1) && *n && !g_ascii_isspace (*n))  
  29.             ++n;  
  30.   
  31.           *n = 0;  
  32.   
  33.           return g_path_get_basename (buf);  
  34.         }  
  35.   
  36.       fclose (fcmd);  
  37.     }  
  38.   
  39.   return NULL;  
  40. }  
 


4. 通过窗口管理器实现,根据应用程序的窗口判断应用程序是否在运行。如果发现对应的应用程序已经在运行,把对应的窗口提到 前面来。这要修改应用程序才行,只有应用程序自己才知道其拥有的窗口的关系,若不加考虑把应用程序的主窗口提到前面来,这也并不见得合适。这种方法只能解 决前两个小问题,命令行参数还是无法传递给第一个运行实例。


5. 应用程序提供一个DBUS服务对象,第一个运行实例作为服务器运行, 第二个运行实例作为客户端运行,第二个运行实例把命令行参数传递给第一个运行实例,然后就退出。第一个运行实例接受到新的命令行参数,作相应的处理,比 如,把相应的窗口提到前面来,根据命令行参数进行处理。这是第二种方法的改进,可以实现全部的功能,缺点是要修改应用程序,不过DBUS服务对象可以通过 一个公共库来实现,应用程序的改动并不大。

 

6. 使用信号量

信号量知识:

http://www.cublog.cn/u/19185/showart_2034149.html

http://www.ibm.com/developerworks/cn/linux/l-osmig1.html

信号量实例:

C代码  收藏代码
  1. #include<stdio.h>  
  2. #include<pthread.h>  
  3. #include<unistd.h>  
  4. #include<fcntl.h>  
  5. #include<sys/stat.h>  
  6. #include<sys/types.h>  
  7. #include<semaphore.h>  
  8. #include<stdlib.h>  
  9. #define N 3  
  10. pthread_mutex_t mutex_w,mutex_r; // 定义读写互斥锁   
  11. sem_t sem_w,sem_r; //定义读写信号量   
  12.   
  13.  int data[N];  
  14. int pos=0;  
  15. void *function_w(void *arg)  
  16. {   
  17.  int w = *(int *)arg;  
  18.  pos = w;  
  19.  while(1)  
  20.  {  
  21.   usleep(100000);  
  22.   sem_wait(&sem_w);//等待可写的资源   
  23.   pthread_mutex_lock(&mutex_w);//禁止别的线程写此资源   
  24.   data[pos] = w;  
  25.   w++;  
  26.   w++;  
  27.   w++;  
  28.   pos++;  
  29.   pos=pos%N;  
  30.   pthread_mutex_unlock(&mutex_w);//别的线程可写此资源   
  31.   sem_post(&sem_r);// 释放一个读资源  
  32.  }  
  33.  return (void *)0;  
  34. }  
  35. void *function_r(void *arg)  
  36. {  
  37.  while(1)  
  38.  {  
  39.   sem_wait(&sem_r);//等待可读的资源   
  40.   pthread_mutex_lock(&mutex_r);//禁止别的线程读此资源   
  41.   printf("%d\n",data[(pos+N-1)%N]);  
  42.   pthread_mutex_unlock(&mutex_r);//别的线程可读此资源   
  43.   sem_post(&sem_w);// 释放一个写资源  
  44.  }  
  45.  return (void *)0;  
  46. }  
  47. int main(int argc, char **argv)  
  48. {  
  49.  pthread_t thread[2*N];  
  50.   
  51.  int i;  
  52.    
  53.   
  54.  pthread_mutex_init(&mutex_w,NULL);  
  55.  pthread_mutex_init(&mutex_r,NULL);  
  56.  sem_init(&sem_w,0,N);  
  57.  sem_init(&sem_r,0,0);  
  58.    
  59.  for(i=0;i<N;i++)  
  60.  {  
  61.   if ( pthread_create(&thread[i],NULL,function_w,(void *)&i) < 0)//创建写线程   
  62.   {  
  63.    perror("pthread_create");  
  64.    exit(-1);  
  65.   }  
  66.  }  
  67.   
  68.  for(i=N;i<2*N;i++)  
  69.  {  
  70.   if ( pthread_create(&thread[i],NULL,function_r,NULL) < 0)//创建读线程   
  71.   {  
  72.    perror("pthread_create");  
  73.    exit(-1);  
  74.   }  
  75.  }  
  76.     
  77.  sleep(1);  
  78.   
  79.  return(0);  
  80. }   
 

 

7. 绑定某一个socket端口, 下次运行就无法再次绑定而退出.

0 0
原创粉丝点击