在我们在做一些程序的时候,可能会涉及到需要运行单一实例的情况,也就是在同一时间,当前程序只运行一次,在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
推荐站内搜索:最好用的开发软件、免费开源系统、渗透测试工具云盘下载、最新渗透测试资料、最新黑客工具下载……
还没有评论,来说两句吧...