为了创建一个单实例应用程序,您有什么建议,以便一次只允许运行一个进程?文件锁,互斥锁还是什么?
原文由 whoi 发布,翻译遵循 CC BY-SA 4.0 许可协议
为了创建一个单实例应用程序,您有什么建议,以便一次只允许运行一个进程?文件锁,互斥锁还是什么?
原文由 whoi 发布,翻译遵循 CC BY-SA 4.0 许可协议
所有学分都归马克·拉卡塔所有。我只是做了一些非常小的修饰而已。
主文件
#include "singleton.hpp"
#include <iostream>
using namespace std;
int main()
{
SingletonProcess singleton(5555); // pick a port number to use that is specific to this app
if (!singleton())
{
cerr << "process running already. See " << singleton.GetLockFileName() << endl;
return 1;
}
// ... rest of the app
}
单例.hpp
#include <netinet/in.h>
#include <unistd.h>
#include <cerrno>
#include <string>
#include <cstring>
#include <stdexcept>
using namespace std;
class SingletonProcess
{
public:
SingletonProcess(uint16_t port0)
: socket_fd(-1)
, rc(1)
, port(port0)
{
}
~SingletonProcess()
{
if (socket_fd != -1)
{
close(socket_fd);
}
}
bool operator()()
{
if (socket_fd == -1 || rc)
{
socket_fd = -1;
rc = 1;
if ((socket_fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
throw std::runtime_error(std::string("Could not create socket: ") + strerror(errno));
}
else
{
struct sockaddr_in name;
name.sin_family = AF_INET;
name.sin_port = htons (port);
name.sin_addr.s_addr = htonl (INADDR_ANY);
rc = bind (socket_fd, (struct sockaddr *) &name, sizeof (name));
}
}
return (socket_fd != -1 && rc == 0);
}
std::string GetLockFileName()
{
return "port " + std::to_string(port);
}
private:
int socket_fd = -1;
int rc;
uint16_t port;
};
原文由 FreeToGo 发布,翻译遵循 CC BY-SA 4.0 许可协议
7 回答5.3k 阅读
3 回答2k 阅读✓ 已解决
4 回答4k 阅读
2 回答3.9k 阅读✓ 已解决
2 回答5.9k 阅读✓ 已解决
2 回答3.2k 阅读✓ 已解决
1 回答3.2k 阅读✓ 已解决
一个好办法是:
请注意,锁定允许您忽略陈旧的 pid 文件(即您不必删除它们)。当应用程序因任何原因终止时,操作系统会为您释放文件锁定。
Pid 文件不是非常有用,因为它们可能是陈旧的(文件存在但进程不存在)。因此,可以锁定应用程序可执行文件本身,而不是创建和锁定 pid 文件。
更高级的方法是使用预定义的套接字名称创建和绑定 unix 域套接字。您的应用程序的第一个实例绑定成功。同样,当应用程序因任何原因终止时,操作系统会取消绑定套接字。当
bind()
失败时,应用程序的另一个实例可以connect()
并使用此套接字将其命令行参数传递给第一个实例。