在我们在做一些程序的时候,可能会涉及到需要运行单一实例的情况,也就是在同一时间,当前程序只运行一次,在Windows与Linux里面的实现方式是不一样的,下面分别记一下:
Windows
在Windows系统中有提供CreateMutex可以创建或打开一个已命名或未命名的互斥对象
函数原型:
 HANDLEWINAPICreateMutex(
 _In_opt_LPSECURITY_ATTRIBUTESlpMutexAttributes,
 _In_BOOLbInitialOwner,
 _In_opt_LPCTSTRlpName
 )lpMutexAttributes指向SECURITY_ATTRIBUTES结构的指针,如果此参数为NULL则此句柄不能由子进程继承
bInitialOwner如果此值为true并且调用者创建了互斥锁,则调用线程将获得互斥锁对象的初始化所有权,否则调用线程不会获得互斥锁的所有权
lpName互斥对象的名称,该名称仅限于MAX_PATH(编译器所支持的最长全路径名的长度),名称区分大小写,如果lpName为NULL,则会创建不带名称的互斥对象嘛,如果lpName与现有事件、信号量、等待定时器、作业或文件映射对象的名称匹配,且这些对象共享相同的命名空间,则该函数将失败,并且GetLastError函数返回ERROR_INVALID_HANDLE
返回值:如果函数成功则返回值是新创建的互斥对象的句柄,如果函数失败则返回NULL,如果互斥锁是一个已命名的互斥锁,并且该对象在此函数调用前就存在,则返回对象是现有对象的句柄,GetLastError返回ERROR_ALREADY_EXISTS
原理是通过CreateMutex函数创建一个命名的互斥对象,如果对象创建成功而且通过调用GetLastError函数获取的返回码为ERROR_ALREADY_EXISTS,则表示该命名互斥对象存在即程序重复运行
编码实现:
 BOOL IsAlreadyRun()
 {
     HANDLE hMutex = NULL;
     bool result = false;
     hMutex = CreateMutex(NULL, FALSE, TEXT("TEST"));
     if (hMutex)
     {
         if (ERROR_ALREADY_EXISTS == ::GetLastError())
         {
             result= TRUE;
 }
     }
     return result;
 }我们可以尝试逆向一下各类EDR或者AV之类的东西,好多都是采用的CreateMutex来运行单一实例的。
Windows运行效果:
Linux
Linux查到的方法觉得文件锁方法效果不错,但是需要高权限运行(也有采用ps来进行判定,但是看了看感觉不优雅),后续如果发现新的方法再做补充,原理是程序开始运行时,往文件里写入进程号,并锁定文件;此时若再运行一个实例,因前一个实例已经锁定文件,此时去锁定文件是失败的。
 static int lockFile(int fd)
 {
     struct flock fl;
     fl.l_type = F_WRLCK;
     fl.l_start = 0;
     fl.l_whence = SEEK_SET;
     fl.l_len = 0;
     fl.l_pid = getpid();  //当前进程号,可写可不写,写了后在用F_GETLK时则可以获取到pid
 
     int ret = fcntl(fd, F_SETLK, &fl);
     printf("file lock ret = %dn", ret);
     return ret;
 }
 
 static int isRunning(const char *procname)
 {
     char buf[16] = {0};
     char fileName[128] = {0};
     snprintf(fileName, sizeof(fileName), "%s%s.pid", PID_FILE_PATH, procname);
 
     //创建文件时如果指定了 O_CREAT,则必须添加权限,否则可能无法读取文件而导致失败
     int g_fd = open(fileName, O_CREAT | O_RDWR, S_IRWXU);
     if(g_fd < 0)
     {
         printf("open file %s failed !n", fileName);
         return 1;
     }
 
     if(-1 == lockFile(g_fd))
     {
         // printf("%s is alread running !n", procname);
         struct flock fl;
         fl.l_type = F_WRLCK;
         fl.l_start = 0;
         fl.l_whence = SEEK_SET;
         fl.l_len = 0;
 
         /*这里获取一下已经运行的实例的进程号*/
         if(fcntl(g_fd, F_GETLK, &fl) == 0)
         {
             printf("%s has been run, pid = %dn", procname, fl.l_pid);
         }
 
         close(g_fd);
         return 1;
     }
     else
     {
         ftruncate(g_fd, 0);
         long pid = getpid();
         snprintf(buf, sizeof(buf), "%ld", pid);
         printf("write pid = %ld to %s!n", pid, fileName);
 
         write(g_fd, buf, strlen(buf) + 1);
         return 0;
     }
 }
 
 Linux中运行效果:
引用:
https://blog.csdn.net/tianyexing2008/article/details/124776360
https://baike.baidu.com/item/CreateMutex/9584433?fr=ge_ala
推荐站内搜索:最好用的开发软件、免费开源系统、渗透测试工具云盘下载、最新渗透测试资料、最新黑客工具下载……




还没有评论,来说两句吧...