守护进程

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

守护进程也称精灵进程(Daemon),是运行在后台的一种特殊进程。它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。守护进程是一种很有用的进程。Linux的大多数服务器就是用守护进程实现的,比如,Internet服务器inetd,Web服务器httpd等,同时,守护进程完成许多系统任务,比如,作业规划进程crond等。


特点如下:

1.守护进程是服务器运行的载体,一般网络服务器必须以守护进程实现;

2.它命名周期只要提供服务,则是7*24时一直运行;

3.它与终端,用户登录与注销无任何关系,其自成进程组自成会话;

4.它的父进程id==1,其为孤儿进程;

5.其命名都以d结尾.

可用以下命令查看系统中的守护进程:

ps axj | grep -E 'd$'

用户自己创建守护进程步骤:

1. 调用umask将文件模式创建屏蔽字设置为0(能够使用户自定义权限设置正确,防止其与系统文件权限关联).
2. 调用fork函数,父进程退出(exit)(若组长进程调用setsid()函数时,则不会成功,所以fork()子进程,父进程退出,从而保证当前运行的进程不是第一个运行的进程也就不为组长进程).

3.调用setsid创建一个新会话。setsid会导致:1)调用进程成为新会话的首进程;  2)调用进程成为一个进程组的组长进程 ;3)调用进程没有控制终端.(再次fork一次,保证daemon进程,之后不会打开tty设备)

4.将当前工作目录更改为根目录(防止目录变更).
5. 关闭不在需要的文件描述符(此时已于控制终端无关,不需要0、1、2等标准输入输出文件).
6. 忽略SIGCHLD信号.


介绍以上setsid函数:

#include <unistd.h>
pid_t setsid(void);    
返回值:调用成功时返回新创建的会话的id(即当前进程的id),出错返回-1.

成功调用该函数的结果是:
1. 创建一个新的会话(Session ),当前进程成为Session Leader,当前进程的id就是Session的id.
2. 创建一个新的进程组,当前进程成为进程组的Leader,当前进程的id就是进程组的id.
3. 如果当前进程原本有一个控制终端,则它与这个控制终端脱离关系,成为一个没有控制终端的进程(所谓脱离控制终端是指,原来的控制终端仍然是打开的,仍然可以读写,但只是一个普通的打开文件已不是控制终端).

注意:调用这个函数之前,当前进程不允许是进程组的Leader,否则该函数返回-1,所以用fork()创建子进程即可以解决.

代码实现:

#include <unistd.h>
#include <signal.h>
#include <stdlib.h>

void mydaemon()
{
	umask(0);    //设置权限 

	if(fork()>0)  //father    //fork父进程退出 
	{
		exit(1);
	}

	setsid();    //调用创建会话函数 

	chdir("/");   //更改目录 

	close(0);     //关闭文件描述符 
	close(1);
	close(2);

	signal(SIGCHLD,SIG_IGN);    //忽略SIGCHLD函数 
} 
int main()
{
	mydaemon();
	//daemon(0,0);   //系统函数创建守护进程 

	while(1)
	{}
	return 0;
}

结果如下:


在系统文件proc中保存CPU进程内存的信息,可查看此守护进程当前工作目录:


文件描述符:



也可以直接使用系统提供的函数创建守护进程:

int daemon(int nochdir,int noclode);
参数:若两个参数都设为0,则将当前工作目录改为根目录下,文件描述符则写入/dev/null下(/dev/null,Linux下黑洞,写入这里面的内容都会被丢弃).

结果如下:





在实现守护进程中,有时会fork()两次,其与fork()一次的区别在于,fork()一次守护进程的pid、gid、sid都是相同的,表示当前进程自成会话自成进程组,fork()两次,其pid与gid、sid不同的,表明此守护进程是属于某一个会话与进程组的。虽然fork()一次使守护进程关闭了与终端联系,但是后期若误操作再次打开终端(或与某一个终端关联),而只有会话首进程可以打开终端设备,所以若在fork()一次,将父进程退出,再次fork子进程作为守护进程继续运行,但其已不是会话首进程也将不能在打开终端,所以两次会使守护进程更加安全。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章