学习笔记之守护进程

Linux C编程一站式学习 学习笔记

一,基本概念

Linux 系统启动时会启动很多系统服务进程,如inetd,init等,这些系统服务进程没有控制终端,不能直接和用户交互。其它进程都是在用户登录或运行程序时创建,在运行结束或用户注销时终止,但系统服务进程不受用户登录注销的影响,它们一直在运行着。这种进程有一个名称叫守护进程(Daemon)。

守护进程的三个特点:后台运行,独立于终端,完成一定的任务。
首先所谓的后台运行过程是一般是在图形界面或是终端不可见的;而独立于终端是说它不和终端联系,运行之后一般不接受终端的输入也不向终端输出;而完成一点的任务是每一个守护进程的运行都是为了完成一定的任务而运行的,这些任务一般都是系统相关的任务。也就是控制台除开这些特殊性以外,守护进程与普通进程基本上没有什么区别。因此,守护进程可以由一个普通进程按照上述的守护进程的特性而改造成为守护进程。

我们用ps axj命令查看系统中的进程。参数a表示不仅列当前用户的进程,也列出所有其他用户的进程,参数x表示不仅列有控制终端的进程,也列出所有无控制终端的进程,参数j表示列出与作业控制相关的信息。

凡是TPGID一栏写着-1的都是没有控制终端的进程,也就是守护进程。在COMMAND一列用[]括起来的名字表示内核线程,这些线程在内核里创建,没有用户空间代码,因此没有程序文件名和命令行,通常采用以k开头的名字,表示Kernel。syslogd负责维护/var/log下的日志文件,可以看出,守护进程通常采用以d结尾的名字,表示Daemon。

二,创建守护进程

先介绍一下Linux中的进程与控制终端,登录会话和进程组之间的关系:进程属于一个进程组,进程组号(GID)就是进程Leader的进程号(PID)。登录会话可以包含多个进程组。这些进程组共享一个控制终端。这个控制终端通常是创建进程的登录终端。

控制终端,登录会话和进程组通常是从父进程继承下来的。我们的目的就是要摆脱它们,使之不受它们的影响。方法是在fork的基础上,调用setsid()使子进程成为会话组长:

#include <unistd.h>
pid_t setsid(void);

该函数调用成功时返回新创建的会话的id(其实也就是当前进程的id),出错返回-1。注意,调用这个函数之前,当前进程不允许是进程组的Leader,否则该函数返回-1。要保证当前进程不是进程组的Leader也很容易,只要先fork再调用setsid就行了。fork创建的子进程和父进程在同一个进程组中,进程组的Leader必然是该组的第一个进程,所以子进程不可能是该组的第一个进程,在子进程中调用setsid就不会有问题了。setsid()调用成功后,进程成为新的会话组长和新的进程组长,并与原来的登录会话和进程组脱离。由于会话过程对控制终端的独占性,进程同时与控制终端脱离。

#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>

void daemonize(void)
{
	pid_t  pid;

	/*
	 * Become a session leader to lose controlling TTY.
	 */
	if ((pid = fork()) < 0) {
		perror("fork");
		exit(1);
	} else if (pid != 0) /* parent */
		exit(0);
	setsid();

	/*
	 * Change the current working directory to the root.
	 */
	if (chdir("/") < 0) {
		perror("chdir");
		exit(1);
	} 

	/*
	 * Attach file descriptors 0, 1, and 2 to /dev/null.
	 */
	close(0);
	open("/dev/null", O_RDWR);
	dup2(0, 1);
	dup2(0, 2);
}

int main(void)
{
	daemonize();
	while(1);
}
按照守护进程的惯例,通常将当前工作目录切换到根目录,将文件描述符0、1、2重定向到 /dev/null。Linux也提供了一个库函数 daemon(3)实现我们的 daemonize函数的功能,它带两个参数指示要不要切换工作目录到根目录,以及要不要把文件描述符0、1、2重定向到 /dev/null

测试如下:

xgx@ubuntu:~/Clan/thread$ ./a.out 
xgx@ubuntu:~/Clan/thread$ ps
  PID TTY          TIME CMD
 7168 pts/2    00:00:02 bash
13463 pts/2    00:00:00 ps
xgx@ubuntu:~/Clan/thread$ ps xj |grep a.out
    1 13462 13462 13462 ?           -1 Rs    1000   0:07 ./a.out
 7168 13467 13466  7168 pts/2    13466 S+    1000   0:00 grep --color=auto a.out




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值