守护进程代码过程概要
来源:互联网 发布:32位ubuntu镜像下载 编辑:程序博客网 时间:2024/06/05 04:39
(一)、守护进程的特征
#ps -axj 其中:-a 显示所有用户所拥有的进程的状态
-x 显示没有控制终端的进程状态
-j 显示与作业相关的的信息:会话ID、进程组ID、控制终端以及终端进程组ID
(二)守护进程的编程规则
(1)、编程规则
1.调用umask()将文件模式创建屏蔽字设置为0.(文件权限——不要变更程序的初始文件权限mode)
由继承提来的文件模式创建屏蔽字可能会拒绝设置某些权限。例如,若守护进程要创建一个组可读、写的文件,而继承的文件模式创建屏蔽字可能屏蔽了这两种权限,于是所要求的组可读、写就不能起作用。
例:umask(0);mode与上umask反码
2.调用fork(),产生一个子进程,然后使父进程退出(exit),子进程变为孤儿进程(init进程的子进程)
这样可以实现:
1)、如果该守护进程是作为一条简单shell命令启动的,那么父进程终止使得shell认为这条命令已经执行完毕(骗了一下os)
2)、子进程继承了父进程组ID,但具有一个新的进程ID,这就保证了子进程不是一个进程组的组长进程
if ((pid = fork()) < 0) perror("%s: can't fork");
else if (pid != 0) exit(0); /* parent */
3. 调用setsid()以创建一个新会话(因为父进程退出了,父进程的会话也退出了)
这样可以实现: 1)、成为新会话的首进程
2)、成为一个新进程组的组长进程
3)、没有终端控制
例:setsid();
4.将当前的工作目录更改为根目录
从父进程处继承过来的当前工作目录可能在一个装配文件系统中。因为守护进程通常在系统再引导之前是一直存在的,所以如果守护进程的当前工作目录在一个装配文件系统中,那么该文件系统就不能被umount,这与装配文件系统的原意不符
if (chdir("/")< 0) perror("can't changedirectory to /");
5、关闭不再需要的文件描述符(守护进程无输入输出,文件描述符继承自父进程,守护进程不需要,全部关闭)
这使守护进程不再持有从其父进程继承过来的某些文件描述符(父进程可能是shell进程,或某个其它进程),可以使用getrlimit()函数来判定最高文件描述符值,并关闭直到该值的所有描述符
Shell指令:#ulimit -a
if (rl.rlim_max == RLIM_INFINITY) rl.rlim_max = 1024;//os只允许一个进程打开1024个文件
for (i = 0; i < rl.rlim_max; i++) close(i);//系统调用
补充:资源限制
系统资源的限制可由getrlimit读取,由setrlimit设置
#include <sys/resource.h>
int getrlimit(int resource, struct rlimit*r_limit);
int setrlimit(int resource, const structrlimit *r_limit);
其中:struct rlimit定义于sys/resource.h,至少包括下列两个成员
{ rlim_t rlim_cur; 当前的软限制(当前文件打开数>1024时,发出警告)
rlim_t rlim_max; 硬限制(当前文件打开数>1024时,由OS杀死进程)
}
rlim_t是一个整数类型用于描述资源级别(typdefunsigned int rlim_t)
通常soft limit是一建议限制,意味着不应超越,如果超越会引起库函数返回错误
Hard limit是硬性限制,若超越意味着将导致系统发送信号以终结程序的运行
例:若超越CPU时间,将导致内核发送SIGXCPU
若超越数据大小限制,将导致内核发送SIGSEGV
一个程序可以设置软限制,一般软限制小于hard limit
仅有具有superuser privileges的程序可以增大hard limit
可以被限制的资源被定义于sys/resource.h中,包括:
CPU使用量
数据段大小
文件大小(<4G)
打开文件数(一般1024)
每个进程用的堆栈大小
每个进程用的地 址空间,一般小于4G
返回值:Successful 0
error -1
6、某些守护进程打开/dev/null(空洞设备)使其具有文件描述符0(stdin)、1(stdout)和2(stderr)
这样任何一个试图读标准输入、写标准输出或标准出错的库例程都不会产生任何效果
因为守护进程并不与终端设备相关联,所以不能在终端设备上显示其输出,也无处从交互用户那里接收输入。
fd0= open("/dev/null", O_RDWR);// 0(stdin)、1(stdout)和2(stderr)全部放进/dev/null(空洞设备)中
fd1 = dup(0);
fd2 = dup(0);
(2)、syslog设施(Linux/UNIX:消息写入syslog设施——写入log文件中)
守护进程存在的一个问题是如何处理出错消息。因为它本就不应该有控制终端,所以不能只是简单地写到标准错误上。也不希望所有守护进程都写到控制台(console)设备上,因为在很多工作站上控制台设备都运行着一个窗口系统。也不希望每个守护进程将它自己的出错消息写到一个单独的文件中。所以,需要有一个集中的守护进程出错记录设施。BSD的syslog设施得到了广泛的应用。大多数守护进程都使用这一设施。
有3种产生日志消息的方法:
1)内核例程可以调用log函数。
任何一个用户进程都可以通过打开(open)并读取(read) /dev/klog设备来读取这些消息。
2)大多数用户进程(守护进程)调用syslog(3)函数来产生日志消息,这使消息被发送至UNIX域数据报套接字/dev/log
3)无论一个用户进程是在此主机上,还是在通过TCP/IP网络连接到此主机的其它主机上,都可以将日志消息发向UDP 514端口。注意syslog函数从不产生这些UDP数据报,它们要求产生此日志消息的进程进行显式的网络编程。
通常,syslogd守护进程读取所有3种格式的日志消息。此守护进程在启动时读一个配置文件---/etc/syslog.conf,该文件决定了不同种类的消息应送向何处
2、syslog设施的接口syslog函数
#include <syslog.h>
void openlog(const char *ident, int option, int facility ); 可选
voidsyslog(int priority, const char *format, ...); 必须
void closelog(void); 可选
说明:调用openlog是可选的。如果不调用openlog,则在第一次调用syslog时,自动调用openlog,
调用closelog也是可选的,因为它只是关闭曾被用于与syslogd守护进程进行通信的描述符
void syslog(int priority, const char *format , ...); 必须
作用:产生一个日志消息,默认打开/dev/log设备
参数:1)priority参数(级别)是facility和level的组合,它们可选取的值分别列于facility和level中 level值按优先级从最高到最低依次排列
2)format参数(自定义的格式):
将format参数以及其它所有参数传到vsprintf函数以便进行格式化。在format中,每个出现的%m字符都先被代换成与errno值对应的出错消息字符串(strerror)
(四)、实现函数---daemon()
作用:使调用程序run in the background,进程成为守护进程
函数:#include <unistd.h>//系统调用
intdaemon(int nochdir, int noclose);
参数:
nochdir 若为0,daemon()将调用进程的当前目录更改为“/ ”
否则,当前进程的工作目录无变化
noclose 若为0,(关)daemon()redirects standard input, standard output and standard error to /dev/null;
否则 no changes are made to these file descriptors.
返回值 //成功与否的标志
On success daemon() returns 0.
If an error occurs, daemon() returns -1 andsets errno to any of the errors specified for the fork and setsid
- 守护进程代码过程概要
- 守护进程:建立过程
- 守护进程创建过程
- 守护进程的建立过程
- 守护进程的创建过程
- 守护进程:代码的分析
- 守护进程c代码实现
- linux守护进程代码分析
- Linux下守护进程的创建过程
- 用perl实现守护进程(daemon)代码
- nginx代码学习_第一章守护进程
- 进程概要
- 守护进程守护自身
- 守护线程、守护进程
- 守护进程
- 守护进程
- 守护进程
- 守护进程
- Webdirver API (Python版)
- js网页添加水印
- android webview JS对话框 不能弹出 解决办法
- 关于见习的课后思考
- TabLayout设置字体为normal
- 守护进程代码过程概要
- FFmpeg源代码简单分析:libavdevice的avdevice_register_all()
- 12. len调试日志(AF)
- 一. SpringBoot集成实例系列-xml型单数据源mybatis
- Windows 平台安装 MongoDB与遇到的问题
- Python小项目四:实现简单的web服务器
- 13. modem调试日志
- centos7下gitlab的配置(nginx冲突、端口更改)
- CSS小技巧