Linux Daemon & 单例模式 设计与实现
PS:要转载请注明出处,本人版权所有。
PS: 这个只是基于《我自己》的理解,
如果和你的原则及想法相冲突,请谅解,勿喷。
前置说明
本文作为本人csdn blog的主站的备份。(BlogID=044)
本文发布于 2017-11-17 16:33:04,现用MarkDown+图床做备份更新。blog原图已丢失,使用csdn所存的图进行更新。(BlogID=044)
环境说明
无
前言
无
Linux Daemo 和 单例模式
Linux 单例模式
原理:创建一个保存进程名的文件,利用linux的文件锁来判断文件是否加锁来判断是否已有相同的程序运行。
例子
int CheckIsSingleton(int *fd)
{
struct flock loglock;
char nowpid[10];
int num;
if (0 > (*fd = open(LOCK_FILE_NAME, O_WRONLY | O_CREAT, 0600)))
{
perror("open lock file failed!");
return -1;
}
/*
struct flock {
...
short l_type; // Type of lock: F_RDLCK,
//F_WRLCK, F_UNLCK
short l_whence; // How to interpret l_start:
//SEEK_SET, SEEK_CUR, SEEK_END
off_t l_start; // Starting offset for lock
off_t l_len; // Number of bytes to lock
pid_t l_pid; // PID of process blocking our lock
// (set by F_GETLK and F_OFD_GETLK)
...
};
As well as being removed by an explicit F_UNLCK, record locks are auto‐
matically released when the process terminates.
*/
memset(&loglock, 0, sizeof(struct flock));
loglock.l_type = F_WRLCK;
loglock.l_whence = SEEK_SET;
if ( 0 > fcntl(*fd, F_GETLK, &loglock) ){//检查是否能够加F_WRLCK锁,不能够确认文件是否有锁。
close(*fd);
perror("fcntl F_WRLCK failed");
_exit(-1);
}
else{
if ( loglock.l_type != F_UNLCK){
close(*fd);
write(2,"check F_WRLCK failed\n",sizeof("check F_WRLCK failed\n"));//stdout was closed!!!
write(2,"The same process is running\n",sizeof("The same process is running\n"));
_exit(-1);
}
}
loglock.l_type = F_WRLCK;
loglock.l_start = 0; //从文件开始加锁
loglock.l_whence = SEEK_SET;
loglock.l_len = 0; //加锁整个文件
if ( 0 > fcntl(*fd, F_SETLK, &loglock) ){
close(*fd);
perror("fcntl F_WRLCK failed");
printf("The same process is running\n");
_exit(-1);
}
num = sprintf(nowpid, "%d",getpid());
write(*fd, nowpid, num);
return 0;
}
Daemon 简单设计
原理
- 利用fork来实现。setsid使当前子进程成为新的进程组长,在使用fork使其与终端脱离,设置工作目录,设置文件掩码
- 利用系统提供的daemon()(此调用来至于glibc)来完成功能。(底层使用fork来实现)
例子
void CreateDaemonProcess_daemon()//根据daemon函数的源码来看,后面补充了一个fork比较安全
{
/*
The daemon() function is for programs wishing to detach themselves from
the controlling terminal and run in the background as system daemons.
If nochdir is zero, daemon() changes the process's current working
directory to the root directory ("/"); otherwise, the current working
directory is left unchanged.
If noclose is zero, daemon() redirects standard input, standard output
and standard error to /dev/null; otherwise, no changes are made to
these file descriptors.
int
daemon(nochdir, noclose)
int nochdir, noclose;
{
int fd;
switch (__fork()) {
case -1:
return (-1);
case 0:
break;
default:
_exit(0);
}
if (__setsid() == -1)
return (-1);
if (!nochdir)
(void)__chdir("/");
if (!noclose) {
struct stat64 st;
if ((fd = open_not_cancel(_PATH_DEVNULL, O_RDWR, 0)) != -1
&& (__builtin_expect (__fxstat64 (_STAT_VER, fd, &st), 0)
== 0)) {
if (__builtin_expect (S_ISCHR (st.st_mode), 1) != 0
#if defined DEV_NULL_MAJOR && defined DEV_NULL_MINOR
&& (st.st_rdev
== makedev (DEV_NULL_MAJOR, DEV_NULL_MINOR))
#endif
) {
(void)__dup2(fd, STDIN_FILENO);
(void)__dup2(fd, STDOUT_FILENO);
(void)__dup2(fd, STDERR_FILENO);
if (fd > 2)
(void)__close (fd);
} else {
// We must set an errno value since no
// function call actually failed.
close_not_cancel_no_status (fd);
__set_errno (ENODEV);
return -1;
}
} else {
close_not_cancel_no_status (fd);
return -1;
}
}
return (0);
}
*/
if (0 > daemon(0, 0))
{
perror("daemon call failed!");
_exit(-1);
}
//setsid();
// int fd;
// if ( 0 > (fd = open("/dev/tty", O_RDWR )) ){
// perror("open tty failed!");
// _exit(-1);
// }
// if ( ioctl(fd, TIOCNOTTY, NULL) < 0){
// perror("ioctl TIOCNOTTY failed!");
// close(fd);
// _exit(-1);
// }
// close(fd);
int pid;
pid = fork();
if (pid == -1)
{
perror("fork first error!");
}
else if (pid > 0)
{ //parent 1
_exit(1);
}
else
{ //child pid==0
}
return;
}
void CreateDaemonProcess_Fork()
{
pid_t pid, pid1, pid2;
pid = fork();
if (pid == -1)
{
perror("fork first error!");
}
else if (pid > 0)
{ //parent 1
_exit(1);
}
else
{ //child pid==0
if (0 > (pid1 = setsid()))
{
perror("setsid() call failed!");
_exit(-1); //
}
else
{
printf("New session id is %d\n", pid1);
}
pid2 = fork();
if (pid2 == -1)
{
perror("fork second error!");
}
else if (pid2 > 0)
{ //parent
_exit(1);
}
else
{
chdir("/"); //change current working directory
umask(0);
return;
}
}
}
说明:
- 双fork的原因是进程组长会开启终端。而我们的daemon程序是不需要终端的。
- 文件掩码用于设置默认的文件权限。
- 子进程会继承父进程的大部分属性,包括已打开文件描述符、文件掩码、工作目录等待,这些根据需求处理。
后记
无
参考文献
- 无
打赏、订阅、收藏、丢香蕉、硬币,请关注公众号(攻城狮的搬砖之路)
PS: 请尊重原创,不喜勿喷。
PS: 要转载请注明出处,本人版权所有。
PS: 有问题请留言,看到后我会第一时间回复。
Linux Daemon & 单例模式 设计与实现的更多相关文章
- 设计模式之PHP项目应用——单例模式设计Memcache和Redis操作类
1 单例模式简单介绍 单例模式是一种经常使用的软件设计模式. 在它的核心结构中仅仅包括一个被称为单例类的特殊类. 通过单例模式能够保证系统中一个类仅仅有一个实例并且该实例易于外界訪问.从而方便对实例个 ...
- 利用单例模式设计数据库连接Model类
之前在<[php]利用php的构造函数与析构函数编写Mysql数据库查询类>(点击打开链接)写过的Mysql数据库查询类还不够完美,利用<[Java]单例模式>(点击打开链接) ...
- python学习(28) 浅谈可变对象的单例模式设计
python开发,有时候需要设计单例模式保证操作的唯一性和安全性.理论上python语言底层实现和C/C++不同,python采取的是引用模式,当一个对象是可变对象,对其修改不会更改引用的指向,当一个 ...
- [转] Linux Daemon Writing HOWTO
Linux Daemon Writing HOWTO Devin Watson v1.0, May 2004 This document shows how to write a daemon in ...
- [转载] Linux Futex的设计与实现
Linux Futex的设计与实现 引子 在编译2.6内核的时候,你会在编译选项中看到[*] Enable futex support这一项,上网查,有的资料会告诉你"不选这个内核不一定能正 ...
- 创建 SysV 风格的 linux daemon 程序
本文介绍如何使用 C 语言创建 Linux 系统中 SysV 风格的 daemon 程序.注意:这是一种旧式的 daemon 程序写法,进入 systemd 时代后是不需要通过这样的方式创建 daem ...
- .NET跨平台实践:.NetCore、.Net5/6 Linux守护进程设计
之前,我写过两篇关于用C#开发Linux守护进程的技术文章,分别是<.NET跨平台实践:用C#开发Linux守护进程>和<.NET跨平台实践:再谈用C#开发Linux守护进程 - 完 ...
- Linux UBI子系统设计初探
问题领域 flash存储设备存在如下特点: 存在坏块 使用寿命较短 存储介质不稳定 读写速度慢 不支持随机访问(nand) 只能通过擦除将0改成1 最小读写单位为page or sub-page 便宜 ...
- Linux Daemon 类程序
1.后台daemon程序(精灵程序) 在Linux中专门提供了一个函数来完成这个daemon化的过程,这个函数的原型如下 int daemon (int __nochdir, int __noclos ...
- python to be linux daemon
所需第三方库:python-daemon[https://pypi.python.org/pypi/python-daemon/] 使用方式: python linux_service.py star ...
随机推荐
- 音频处理实用AI工具
最近在做音频处理相关的工作,主要有以下几个好用的工具. 1. 语音转文字--whisper 这是一款由OpenAI开发的语音转文字工具,项目地址位于:openai/whisper. 这个工具是用来生成 ...
- Windows上同时使用有线网络及无线网络连接配置
由于公司搬到了新的办公地点,公司内部只有内网,当需要连接互联网查询资料时只能切换网络,非常麻烦.所以为了能够同时连接连接公司内网,又能够访问互联网,这里介绍如何同时连接无线和有线. 有线网络:10.3 ...
- VMware全版本下载工具
有很多小伙伴想下载适合自己的虚拟机版本,但是官网全是英文看不懂 百度找的还怕带病毒 这里栀煜单独制作了个工具,内置vm9 10 11 12 14 15 16 17版本的虚拟机下载地址,都是官方版 不是 ...
- JS leetcode 反转字符串中的单词 III 题解分析
壹 ❀ 引 又到了快乐的leetcode算法时间,今天的题目特别特别简单,来自leetcode557. 反转字符串中的单词 III,题目描述如下: 给定一个字符串,你需要反转字符串中每个单词的字符顺序 ...
- NC17889 新建 Microsoft Office Word 文档
题目链接 题目 题目描述 CSL正在学习<计算机办公自动化>文件的建立与删除. CSL发现,当他新建一个word文档时,会得到一个名为"新建 Microsoft Office W ...
- 【OpenGL ES】Blinn改进的冯氏光照模型
1 前言 光照元素主要有环境光(ambient).漫反射光(diffuse).镜面反射光(specular),光照模型主要有冯氏模型和 Blinn 改进的冯氏模型,两者区别在与镜面反射光的计算,冯 ...
- 中国特色AI创业:在OpenAI阴影下的探索与挑战
在中国特色背景下,AI创业领域的一些荒诞现象以及对AI创业者.投资人的心态和影响.同时,OpenAI的强大影响力和国内AI领域的创业现状. 首先,小红书上关于中国版Sora项目的荒诞段子,揭示了部分人 ...
- 【Android 逆向】【攻防世界】RememberOther
1. apk安装到手机,提示输入用户名注册码 2. jadx 打开apk public boolean checkSN(String userName, String sn) { try { if ( ...
- LibModbus库开发笔记(一):libmodbus库介绍、编译和基础工程模板
前言 本文章讲解libmodbus. libModbus介绍 libmodbus是一个免费软件库,可根据Modbus协议发送/接收数据.该库用C编写,并支持RTU(串行)和TCP(以太网) ...
- 进程之间共享数据Manager,线程相关使用Thread,用类定义线程,守护线程setDaemon,线程锁Lock,线程信号量Semaphore---day32
1.Manager # ### Manager (list列表,dict字典)进程之间的共享数据(列表或字典等) from multiprocessing import Process,Manager ...