linux 进程(关于守护进程、检查一个进程是否活着、如何写一个进程号文件)
来源:互联网 发布:共享单车app源码 编辑:程序博客网 时间:2024/04/28 01:59
本文主要包括三个部分:
一是如何实现一个守护进程,二是如何检测一个进程是否活着,三是保证某一执行文件只有一个实例在运行。
/*
* 1.守护进程
*/
守护进程的最大特点就是脱离了中断,Linux提供了一个系统调用daemon(),要想自定义实现的话,主要包括以下六个步骤:
1.第一步是使用umask函数,把所有的文件屏蔽字置0。文件屏蔽字是可以继承的,当你有相关操作时,如果你要创建一个文件,继承过来的屏蔽字可能阻止你创建相关属性的文件。比如:如果你明确的创建一个文件为组可读,组可写。如果你没有把屏蔽字清零,那么继承过来的屏蔽字可能不允许你添加这两个属性。
2.第二步,创建一个子进程,并且令父进程退出。这样做有以下几个好处:一,如果守护进程是一个简单的shell命令启动的,那么父进程的终止可以使shell认为这个命令已经执行结束了。二,子进程继承了父进程的组ID,但又有自己的进程ID,所以我们可以保证目前的子进程不是进程组长。这一步也是我们接下来要用到的setid函数之前的必要条件。
3.使用setsid函数创建一个新的对会话。首先,该进程变为一个新的会话组的会话头。其次,成为了新的进程组的组长。最后该进程不再控制终端。在system V 下,一些人建议在此时重新fork一次,并且令父进程退出。第二个子进程仍然是一个守护进程。这样做可以保证当前进程不是一个会话组的组长,这样就可以防止他获得控制终端的能力。作为选择,为了防止获得终端的控制权,确定打开终端驱动时明确设置O_NOCTTY。
4.把当前工作目录变为根目录。当前的工作目录是继承父进程的。守护进程是一直存在的,除非你重启计算机。如果你的守护进程是挂载到文件系统上的,那这个文件系统就不能卸载掉。
5.不需要的文件描述符应当关掉。这样可以防止守护进程持有从父进程继承过来的文件描述符。我们可以获取最大的文件描述符,或者使用getrlimit函数来决定最大的文件描述符的值。并且全部关闭。(非必要)
6.一些守护进程把0,1,2这三个文件描述符指向/dev/null,这样的话,当库函数试图通过标准输入输出,标准错误时是没有效果的。当一个守护进程脱离了终端时,就没有地方打印信息;也没有地方接收来自用户的交互式输入。甚至当一个守护进程从一个交互式的会话开始,守护进程在后台运行,登陆会话关闭也不会影响到守护进程。如果其他用户用同样的终端登陆,我们不用设想从守护进程打印信息到终端,也别指望用户读取守护进程。
以上主要参考:http://www.cnblogs.com/iceocean/articles/1650475.html
/*
* 2.如何检查一个进程是否活着
*/
判断一个进程是否活着,我们主要是通过kill这一系统调用来完成,先看一下kill的manual page:
- #include <sys/types.h>
- #include <signal.h>
- int kill(pid_t pid, int sig)
- DESCRIPTION
- The kill() system call can be used to send any signal to any process
- group or process.
- If pid is positive, then signal sig is sent to pid.
- If pid equals 0, then sig is sent to every process in the process group
- of the current process
- If pid equals -1, then sig is sent to every process for which the call-
- ing process has permission to send signals, except for process 1
- (init), but see below.
- If pid is less than -1, then sig is sent to every process in the pro-
- cess group -pid.
- If sig is 0, then no signal is sent, but error checking is still per-
- formed.
- if you can send a signal to PID, and returns 1 if you can't (don't have access or invalid PID)。
所以kill(pid,0)可以用于检测一个为pid的进程是否还活着[在shell下面可以用ps来查找],基本逻辑如下:
- if(kill(pid,0)!=0)
- it's dead.
- else
- it's alive.
/*
*3.保证某一执行文件只有一个实例在运行
*/
这样的需求主要是解决保证只有同时只有一个这样的进程在运行,像mysql都这样处理:
1.启动进程后,先检查pid文件是否存在,存在则读取之前写入的pid,然后用上面的kill(pid,0);来检查是否活着,
2.活着则退出进程,不允许再启动一个进程,否则启动并将当前的pid写入pid文件。写入的时候要锁住文件,避免
其他进程也往里面写,主要是lockf这个系统调用,方法是:
- /**
- * @Brief write the pid into the szPidFile
- *
- * @Param szPidFile name of pid file
- */
- void writePidFile(const char *szPidFile)
- {
- /*open the file*/
- char str[32];
- int lfp = open(szPidFile, O_WRONLY|O_CREAT|O_TRUNC, 0600);
- if (lfp < 0) exit(1);
- /*F_LOCK(block&lock) F_TLOCK(try&lock) F_ULOCK(unlock) F_TEST(will not lock)*/
- if (lockf(lfp, F_TLOCK, 0) < 0) {
- fprintf(stderr, "Can't Open Pid File: %s", szPidFile);
- exit(0);
- }
- /*get the pid,and write it to the pid file.*/
- sprintf(str, "%d\n", getpid()); // \n is a symbol.
- ssize_t len = strlen(str);
- ssize_t ret = write(lfp, str, len);
- if (ret != len ) {
- fprintf(stderr, "Can't Write Pid File: %s", szPidFile);
- exit(0);
- }
- close(lfp);
- }
- linux 进程(关于守护进程、检查一个进程是否活着、如何写一个进程号文件)
- linux 进程(关于守护进程、检查一个进程是否活着、如何写一个进程号文件)
- linux 进程(关于守护进程、检查一个进程是否活着、如何写一个进程号文件)
- linux 进程(关于守护进程、检查一个进程是否活着、如何写一个进程号文件)
- 如何写好一个守护进程
- 【Linux】守护进程以及实现一个守护进程
- 编写一个守护进程
- 编写一个守护进程
- 实现一个守护进程
- 用守护进程来判断一个进程是否运行
- 如何写一个简单的守护(精灵)进程原型
- 如何写一个简单的守护(精灵)进程原型
- 六十 如何写一个简单的守护(精灵)进程原型
- 怎么写一个简单的守护进程
- 用PHP写一个Daemon守护进程
- 写一个bash版的守护进程
- 如何实现多进程写一个文件
- 如何实现多进程写一个文件
- 对项目开发管理的一些思考
- 优秀程序员因何而优秀?
- Linux——信号量(同步)
- 2014腾讯校招软开类笔试题
- CSS 继承
- linux 进程(关于守护进程、检查一个进程是否活着、如何写一个进程号文件)
- 关于java方法调用时产生的StackFrame内部内容。
- NSString 常用处理方法
- java创建文件和目录
- [转]win7中java环境变量配置
- 学习Linux系统的十一点建议
- 从 C/C++ 程序调用 Java 代码
- 服务器集群后,共享session问题
- Unreal Enginer4特性介绍-牛B闪闪的UE4