Linux下防止重复启动相同程序的俩种处理方式

第一种方式:
//该防止重复启动相同程序的基本原理是基于父子进程共享内存和文件强制锁,子进程调用实现功能的函数

//文件强制锁:调用flock函数设置文件为LOCK_EX强制锁,可防止独立的不同进程访问同一文件,达到判断程序是否已在运/
 
//行的目的; 
 
//父子进程共享内存:子进程如果得到文件锁,说明该程序没有被启动,同时将共享内存struct shared_use_st中written 
//置为1,父进程等待子进程结束;子进程如果得不到文件锁,说明该程序已经被启动,共享内存struct shared_use_st中w 
//ritten不会被置为1,父进程会杀死子进程,同时退出,达到关闭死进程的效果;  
 
#include <iostream> 
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sstream>
#include <sys/shm.h>
#include <sys/wait.h>

#define FLOCKFILEPATH "/etc/wifi/WDWifiDetector.flock"//自定义要加文件锁的文件路径

struct shared_use_st
{
    int written;//作为一个标志,非0:表示可读,0表示可写
    char text[1024];//记录写入和读取的文本
};

int MyMain();//自己要实现功能的函数
 
int main()
{
 pid_t childPid;
 void *shm = NULL;
 struct shared_use_st *shared;
 int shmid;
 shmid = shmget((key_t)1234, sizeof(struct shared_use_st), 0666|IPC_CREAT);
 if(shmid == -1)
 {
  fprintf(stderr, "shmget failed\n");
  exit(0);
 }
 shm = shmat(shmid, 0, 0);
 if(shm == (void*)-1)
 {
  fprintf(stderr, "shmat failed\n");
  exit(0);
 }
 shared = (struct shared_use_st*)shm;
 shared->written = 0;
 if((childPid = fork()) < 0)
 {
  std::cout<<"fork err!"<<std::endl;
  return 1;
 }
 if(childPid == 0)
 {
  int fd = open(FLOCKFILEPATH, O_RDWR | O_CREAT, S_IRWXU);
  flock(fd, LOCK_EX);//如果程序已启动,则该次启动会在这里一直等待已启动程序将文件锁释放
  shared->written = 1;
  MyMain();//调用实现功能的函数
 }
 else
 {
  sleep(3);
  if(shared->written == 0)
  {
   std::stringstream ss;
   ss<<"kill -9 "<<childPid;
   system(ss.str().c_str());
   std::cout<<"Error:Can't repeat to launch the program!"<<std::endl;
   std::cout<<"This program had been launched! Please close previous program and then launch this program!"<<std::endl;
   return 1;
  }
  int status;
  waitpid(childPid, &status, 0);
  std::cout<<"parent pid is over!"<<std::endl;
 }
 return 0;
}

//资料参考博客: 
//http://blog.csdn.net/ljianhui/article/details/10253345  
// 
第二种方式:
比较简单的进程号获取比较:
	int ret = system("echo $(pgrep WDWifiDetector) |grep -c \" \"");

	if(!ret)//如果只有当前的进程则ret==0;如果已经开启了该程序,旧的进程号加上目前的进程号则ret==256
	{
		std::cout<<"Error:Can't repeat to launch the program!"<<std::endl;

		return 1;
	}
	
解释:
echo $(pgrep WDWifiDetector) |grep -c \" \":
    pgrep WDWifiDetector:获取程序名称为WDWifiDetector的进程是否存在;
    grep -c \" \":判断进程是否是俩(当前进程和已经开启的进程);


你可能感兴趣的:(linux,内存共享,文件强制锁,重复启动程序)