who*_*hoi 52 c c++ linux single-instance
为了创建单个实例应用程序,您的建议是什么,以便一次只允许一个进程运行?文件锁,互斥还是什么?
Max*_*kin 60
一个好方法是:
#include <sys/file.h>
#include <errno.h>
int pid_file = open("/var/run/whatever.pid", O_CREAT | O_RDWR, 0666);
int rc = flock(pid_file, LOCK_EX | LOCK_NB);
if(rc) {
if(EWOULDBLOCK == errno)
; // another instance is running
}
else {
// this is the first instance
}
Run Code Online (Sandbox Code Playgroud)
请注意,锁定允许您忽略过时的pid文件(即您不必删除它们).当应用程序因任何原因终止时,操作系统会为您释放文件锁定.
Pid文件不是非常有用,因为它们可能是陈旧的(文件存在但过程不存在).因此,可以锁定应用程序可执行文件本身,而不是创建和锁定pid文件.
更高级的方法是使用预定义的套接字名称创建和绑定unix域套接字.绑定成功应用于您的应用程序的第一个实例.同样,当应用程序因任何原因终止时,操作系统会解除套接字的绑定.当bind()失败的应用程序的另一个实例可以connect()和使用此接口将其命令行参数传递到第一个实例.
Mar*_*ata 13
这是C++的解决方案.它使用Maxim的套接字推荐.我比基于文件的锁定解决方案更喜欢这个解决方案,因为如果进程崩溃并且没有删除锁定文件,则基于文件的解决方案会失败.另一个用户将无法删除该文件并将其锁定.进程退出时会自动删除套接字.
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
}
Run Code Online (Sandbox Code Playgroud)
#include <netinet/in.h>
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;
};
Run Code Online (Sandbox Code Playgroud)
小智 5
避免基于文件的锁定
避免基于文件的锁定机制来实现应用程序的单例实例总是好的.用户始终可以将锁定文件重命名为其他名称,然后再次运行该应用程序,如下所示:
mv lockfile.pid lockfile1.pid
Run Code Online (Sandbox Code Playgroud)
在lockfile.pid运行应用程序之前,基于哪个锁定文件检查是否存在.
因此,对于仅对内核直接可见的对象,最好使用锁定方案.因此,任何与文件系统有关的事情都是不可靠的.
所以最好的选择是绑定到inet套接字.请注意,unix域套接字驻留在文件系统中并且不可靠.
或者,您也可以使用DBUS来完成.