判断程序实例是否已经运行的N种方法
来源:互联网 发布:godaddy域名优惠 编辑:程序博客网 时间:2024/05/17 22:02
转自:http://socol.iteye.com/blog/687728
1. 在创建的文件中写入进程的ID,如果机器非正常退出,重启后先读取这个文件,得到进程ID,再根据ID判定进程是否正在运行,如果不是,则把文件删除掉。这样就不会发生不删除文件,程序运行不起来的问题了。
2. 打开一个文件,然后锁定,新运行的程序会试图再次锁定该文件,但是因为已经被锁定,所以会返回错误信息。据此就可以判断是否有程序已经运行。设置FD_CLOEXEC后,只要程序终止,都可以再次锁定。
通常精灵进程都使用这种方法,比如apache等等,而且默认都会在/var/run目录
- #include <stdlib.h>
- #include <stdio.h>
- #include <fcntl.h>
- #include <signal.h>
- #include <unistd.h>
- #include <sys/stat.h>
- #include <errno.h>
- #include <QtCore/QCoreApplication>
- #include <QDebug>
- #define PIDFILE "/var/run/my.pid"
- #define write_lock(fd,offset,whence,len) lock_reg(fd,F_SETLK,F_WRLCK,offset,whence,len)
- #define FILE_MODE (S_IRWXU|S_IRWXG|S_IRWXO)
- int lock_reg (int fd, int cmd, int type, off_t offset, int whence, off_t len)
- {
- struct flock lock;
- lock.l_type = type;
- lock.l_start = offset;
- lock.l_whence = whence;
- lock.l_len = len;
- int ret = fcntl(fd, cmd, &lock);
- return ret;
- }
- bool isSingleton()
- {
- int fd,val;
- char buf[10];
- if ((fd = open(PIDFILE, O_WRONLY|O_CREAT, FILE_MODE)) < 0) {
- qDebug() << "daemon need run by root. open" << PIDFILE << "error.";
- return false;
- }
- if(write_lock(fd, 0, SEEK_SET, 0) < 0)
- {
- if (errno == EACCES || errno == EAGAIN)
- qDebug() << "daemon has been in running!";
- else
- qDebug() << "daemon other error.";
- return false;
- }
- if (ftruncate(fd, 0) < 0) {
- qDebug() << "ftruncate error.";
- return false;
- }
- sprintf(buf,"%d\n",getpid());
- if (write(fd, buf, strlen(buf)) != strlen(buf)) {
- qDebug() << "pid write error.";
- return false;
- }
- // close file descriptor
- if ((val = fcntl(fd, F_GETFD, 0)) < 0) {
- qDebug() << "fcntl F_GETFD error.";
- return false;
- }
- val |= FD_CLOEXEC;
- if (fcntl(fd, F_SETFD, val) < 0) {
- qDebug() << "fcntl F_SETFD error.";
- return false;
- }
- return true;
- }
- void initDaemon(void)
- {
- pid_t pid, sid;
- if((pid = fork()) < 0)
- return;
- else if(pid != 0)
- exit(0); /* parent exit */
- /* child continues */
- sid = setsid(); /* become session leader */
- if (sid < 0) {
- exit(-1);
- }
- /* change working directory */
- if ((chdir("/")) < 0) {
- exit(-1);
- }
- umask(0); /* clear file mode creation mask */
- #if 0
- close(0); /* close stdin */
- close(1); /* close stdout */
- close(2); /* close stderr */
- #endif
- }
- int main(int argc, char *argv[])
- {
- initDaemon();
- if (!isSingleton())
- return 0;
- QCoreApplication a(argc, argv);
- return a.exec();
- }
3. 遍历/proc目录下的进程信息,如果应用程序对应的进程存在,则让认为应用程序已经在运行。然后强制关闭该应用程序,用新的命令行参数重新运行 它。这样做的优点是实现简单,到达了我们预期的目标。缺点是强制kill第一个运行实例太野蛮,可能会造成数据丢失,另外创建新进程的开销会让用户感觉反 应迟钝。
- /*
- * getpid shell: pidof XXX
- * Returns the executable name for given pid.
- */
- static gchar *
- pid_to_binary_name (gint pid)
- {
- gchar * cmd_f;
- FILE * fcmd;
- if (pid <= 0)
- return NULL;
- cmd_f = g_strdup_printf ("/proc/%d/cmdline", pid);
- fcmd = fopen (cmd_f, "r");
- g_free (cmd_f);
- if (fcmd)
- {
- gchar buf[256];
- if (fgets (buf, sizeof (buf), fcmd))
- {
- /*
- * 0-terminate at first whitespace.
- */
- gchar *n = &buf[0];
- while ((n < &buf[0] + sizeof(buf) - 1) && *n && !g_ascii_isspace (*n))
- ++n;
- *n = 0;
- return g_path_get_basename (buf);
- }
- fclose (fcmd);
- }
- return NULL;
- }
4. 通过窗口管理器实现,根据应用程序的窗口判断应用程序是否在运行。如果发现对应的应用程序已经在运行,把对应的窗口提到 前面来。这要修改应用程序才行,只有应用程序自己才知道其拥有的窗口的关系,若不加考虑把应用程序的主窗口提到前面来,这也并不见得合适。这种方法只能解 决前两个小问题,命令行参数还是无法传递给第一个运行实例。
5. 应用程序提供一个DBUS服务对象,第一个运行实例作为服务器运行, 第二个运行实例作为客户端运行,第二个运行实例把命令行参数传递给第一个运行实例,然后就退出。第一个运行实例接受到新的命令行参数,作相应的处理,比 如,把相应的窗口提到前面来,根据命令行参数进行处理。这是第二种方法的改进,可以实现全部的功能,缺点是要修改应用程序,不过DBUS服务对象可以通过 一个公共库来实现,应用程序的改动并不大。
6. 使用信号量
信号量知识:
http://www.cublog.cn/u/19185/showart_2034149.html
http://www.ibm.com/developerworks/cn/linux/l-osmig1.html
信号量实例:
- #include<stdio.h>
- #include<pthread.h>
- #include<unistd.h>
- #include<fcntl.h>
- #include<sys/stat.h>
- #include<sys/types.h>
- #include<semaphore.h>
- #include<stdlib.h>
- #define N 3
- pthread_mutex_t mutex_w,mutex_r; // 定义读写互斥锁
- sem_t sem_w,sem_r; //定义读写信号量
- int data[N];
- int pos=0;
- void *function_w(void *arg)
- {
- int w = *(int *)arg;
- pos = w;
- while(1)
- {
- usleep(100000);
- sem_wait(&sem_w);//等待可写的资源
- pthread_mutex_lock(&mutex_w);//禁止别的线程写此资源
- data[pos] = w;
- w++;
- w++;
- w++;
- pos++;
- pos=pos%N;
- pthread_mutex_unlock(&mutex_w);//别的线程可写此资源
- sem_post(&sem_r);// 释放一个读资源
- }
- return (void *)0;
- }
- void *function_r(void *arg)
- {
- while(1)
- {
- sem_wait(&sem_r);//等待可读的资源
- pthread_mutex_lock(&mutex_r);//禁止别的线程读此资源
- printf("%d\n",data[(pos+N-1)%N]);
- pthread_mutex_unlock(&mutex_r);//别的线程可读此资源
- sem_post(&sem_w);// 释放一个写资源
- }
- return (void *)0;
- }
- int main(int argc, char **argv)
- {
- pthread_t thread[2*N];
- int i;
- pthread_mutex_init(&mutex_w,NULL);
- pthread_mutex_init(&mutex_r,NULL);
- sem_init(&sem_w,0,N);
- sem_init(&sem_r,0,0);
- for(i=0;i<N;i++)
- {
- if ( pthread_create(&thread[i],NULL,function_w,(void *)&i) < 0)//创建写线程
- {
- perror("pthread_create");
- exit(-1);
- }
- }
- for(i=N;i<2*N;i++)
- {
- if ( pthread_create(&thread[i],NULL,function_r,NULL) < 0)//创建读线程
- {
- perror("pthread_create");
- exit(-1);
- }
- }
- sleep(1);
- return(0);
- }
7. 绑定某一个socket端口, 下次运行就无法再次绑定而退出.
- 判断程序实例是否已经运行的N种方法
- 判断程序实例是否已经运行的N种方法
- 判断程序实例是否已经运行的N种方法
- 判断程序是否已经运行
- 判断是否已经运行了某个程序
- java判断一个程序是否已经运行
- 如何判断程序是否重复运行的几种方法
- 如何判断程序是否重复运行的几种方法
- 如何判断程序是否重复运行的几种方法
- 如何判断程序是否重复运行的几种方法
- C# winform 判断程序是否已经在运行 判断程序是否已经打开
- 判断程序已经运行
- 判断自己的程序是否已经打开
- 判断程序是否已经运行,然后kill旧的或者新的.
- 判断程序是否已经运行,然后kill旧的或者新的.
- UNIX-判断程序是否已经运行的脚本在crontab与命令行下的不同
- 判断已经声明的方法是否实现
- 判断程序是否已经打开
- 黑马程序员_007_List 与 Set
- c++中日期转换
- android浏览器插件
- yii zii.widgets.grid.CGridView 时间插件查询
- 小记,android 手机不显示百度地图,全白网格
- 判断程序实例是否已经运行的N种方法
- 【live555】MediaSink类分析
- 黑马程序员_008_Map 的两种取出方式
- Error And Bias
- Oracle数据类型浅析:varchar2
- 睡眠--TASK_INTERRUPTIBLE and TASK_UNINTERRUPTIBLE
- Windows 下 AnacondaCE 安装 Theano 0.6.0rc3 问题
- Navicat for Oracle的安装配置过程
- Oracle中的Raw类型