守护进程
守护进程是一个后台程序,它无需用户输入就能运行,经常是提供某种服务。Linux做为服务器,主要的进程也都是为系统或者用户提供后台服务功能。
常见的守护进程偶遇Web服务器,邮件服务器以及数据库服务器。
守护进程不能够控制终端,所以任何输入或者输出都需要特殊处理
守护进程看上去很神秘,但如果牢记几条规则并知道几个关键函数,工作就简单了。
首先执行fork后让父进程退出,和多数进程一样,一个守护进程是从shell脚本或者命令行启动的。
但守护进程和应用程序不一样,因为它们不是交互式的。
父进程在fork子进程退出后就消除了控制终端。
守护进程既不需要从标准输入设备输入信息,也不需要从标准输出设备输出信息,多处理信号。
下一步在子进程中调用setsid,取消进程和任何控制终端的关联。
下一步是让根目录成为子进程的当前工作目录。
因为进程如果它的当前目录是在一个被安装的文件系统上,那么就会妨碍这个文件系统被卸载(这个不是必须的)
接下来设置进程的umask为0,为了避免守护进程集成的umask受到创建文件和目录操作的干扰,这一步是必要的。
如果一个进程集成了父进程的umaks055,它屏蔽了group和other的执行权。如果守护进程接着创建文件,那么对group和other用户操作这个文件带来麻烦。
守护进程调用umask0避免了这种情况,当创建文件的时候给予守护进程更大的灵活性。(umask为创建文件是文件默认具不具有的权限,如055 权限如上述)
最后关闭进程继承的任何不必要的文件描述符。
创建守护进程:
-父进程fork后,exit退出
-在子进程调用setsid
-让根目录”/”成为子进程的工作目录
-把子进程的umask变为0
-关闭任何不需要的文件描述符
setsid函数
pid_t setsid();
setsid函数创建一个新会话和一个新进程组,然后守护进程成为会话的领导,以及新进程组的进程组领导。
setsid函数保证新会话没有控制终端
如果调用进程已经是I一个进程组的领导进程,则setsid调用失败
setsid调用成功返回新会话ID, 失败返回-1, 并设置errno
chdir函数
int chdir(const char *pathname)
修改当前工作目录
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
int main(void)
{
pid_tpid = fork();
if(pid> 0)
{
exit(0);
}
if(pid== 0)
{
setsid();
chdir("/");
umask(0);
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
while(1)
{
sleep(1);
}
}
return EXIT_SUCCESS;
}