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 ...
随机推荐
- 【进阶篇】Java 实际开发中积累的几个小技巧(一)
目录 前言 一.枚举类的注解 二.RESTful 接口 三.类属性转换 四.Stream 流 五.判空和断言 5.1判空部分 5.2断言部分 文章小结 前言 笔者目前从事一线 Java 开发今年是第 ...
- 小知识:在Exadata平台上使用ExaWatcher收集信息
在非Exadata平台上,我们通常会使用DBA已经很熟悉的OSW,如果有不熟悉的朋友可以参考我之前的随笔初步了解OSW: OSW 快速安装部署 OSW Analyzer分析oswbb日志发生异常 而在 ...
- Linux centos7.6 在线及离线安装postgresql12 详细教程(rpm包安装)
一.在线安装 官网找到对应的版本 PostgreSQL: https://www.postgresql.org/ 1.配置yum源 sudo yum install -y https://downl ...
- 2023年多校联训NOIP层测试2
2023年多校联训NOIP层测试2 爆零了 T1 HDU 4786 Fibonacci Tree \(0pts\) @wangyunbiao: 不可以,总司令 我:不,可以,总司令 @wangyunb ...
- 扯淡的DevOps,我们开发根本不想做运维!
引言 最初考虑引用" DevOps 已死,平台工程才是未来"作为标题,但这样的表达可能太过于绝对.最终,决定用了"扯淡的"这个词来描述 DevOps,但这并不是 ...
- NC53079 Forsaken喜欢数论
题目链接 题目 题目描述 Forsaken有一个有趣的数论函数.对于任意一个数 \(x\) , \(f(x)\) 会返回 \(x\) 的最小质因子.如果这个数没有最小质因子,那么就返回0. 现 ...
- python web连接mysql数据库
一定要commit,否则数据库不会发生改变!!! 1.使用python写入内容到数据库 import pymysql # 记得下载并引入pymysql # 1.连接mysql,db:声明数据库 con ...
- Lucene介绍与使用
Lucene介绍与使用 原文链接:https://blog.csdn.net/weixin_42633131/article/details/82873731 不选择使用Lucene的6大原因? 原文 ...
- Mqtt开发笔记:Mqtt服务器搭建
若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/ar ...
- Ubuntu如何卸载mysql
首先在终端中查看MySQL的依赖项:dpkg --list|grep mysql 卸载: sudo apt-get remove mysql-common 卸载:sudo apt-get autore ...