1、普通进程运行观察
进程有对应的终端,终端退出,那么该进程也就消失了。父进程是bash。
终端被占用。
2、守护进程基本概念
守护进程是一种长期运行的进程,在后台运行,不跟任何终端关联。
基本特点:生存周期比较长,一般是操作系统启动的时候启动,
操作系统关闭的时候才关闭。
守护进程跟终端无关联,没有控制终端。不随终端退出而退出。
守护进程在后台运行。
linux操作系统本身有很多守护进程在默默运行,维持着系统的日常活动,30-50个。
ppid = 0的属于内核进程,跟随系统启动而启动,生命周期贯穿整个系统。
比如:init,kthreadd
cmd列名字带【】的就是内核守护进程。
init:也是系统守护进程,负责启动各运行层次特定的系统服务。
所以很多进程的ppid是init。。也负责收养孤儿进程。
cmd列中不带【】的是普通守护进程(用户守护进程)
共同点总结:大多数守护进程都是以超级用户权限运行的;
守护进程没有控制终端,TT这列显示?
a、内核守护进程以无控制终端方式启动
b、普通守护进程可能是守护进程调用了setsid的结果(无控制终端)。
守护进程虽然可以从终端启动,但和终端不挂钩。守护进程实在后台爱运行,不应该从键盘上接收任何东西。也不应该把输出结果打印大终端上来。所以要把守护进程的标准输入、标准输出重定向到空设备。
3、守护进程编写规则
a、调用umask(0):用来限制(屏蔽)一些文件权限的。
b、fork一个子进程出来,然后父进程退出,把控制终端空出来,
fork的目的是想成功调用setsid()来建立新会话。
目的是让子进程有单独的sid,而且子进程也成为新进程组的组长进程,
同时不关联任何终端了。
c、把守护进程的标准输入、标准输出重定向到空设备。从而确保不从键盘接收,
不打印到屏幕。
int fd;
fd = open("/dev/null" ,O_RDWR);
dup2(fd, STDIN_FILENO); //复制文件描述符,类似指针赋值,
标准输入指向黑洞。
dup2(fd, STDOUT_FILENO);
if(fd > STDERR_FILENO)
close(fd); //等价于fd = NULL
3.1、文件描述符
正数,用来标识一个文件。当你打开一个存在的文件,
或者创建一个新文件,操作系统都会返回这个文件描述符。
后续对文件操作的一些函数,都会调用到这个文件描述符作为参数。
三个特殊的文件描述符:0(标准输入),1(标准输出),2(标准出错)
分别对应的符号常量:STDIN_FILENO,STDOUT_FILENO,STDERR_FILENO
类Unix默认从STDIN_FILENO读数据,从STDOUT_FILENO写数据。
一切皆文件。所以以上都看成文件。
程序启动,自动打开。
3.2、输入输出重定向
输出重定向:1>/dev/null
3.3、空设备
/dev/null,是一个特殊的设备文件,丢弃写入。
3.4、实现范例,nginx提炼出来可用于商业用途
|#include <sys/stat.h>
|#include <fcntl.h>
//创建守护进程
int ngx_daemon()
{
int fd;
switch(fork())
{
case -1:
//创建子进程失败,这里可以写日志。。。。
return -1;
case 0:
//子进程,走到这里,直接break
break;
default:
//父进程,直接退出
exit(0);
}
//只有子进程流程才能走到这里
if(setsid() == -1){ //脱离终端,终端关闭,将跟此子进程无关
//记录错误日志
return -1;
}
umask(0); //设置为0,不要让它来限制文件权限,以免引起混乱
fd = open("/dev/null", O_RDWR); //打开黑洞设备,以读写方式打开
if(fd == -1){
//记录错误日志
return -1;
}
if(dup2(fd, STDIN_FILENO) == -1){ //先关闭STDIN_FILENO,
//改变指向之前,先close
//记录错误日志
return -1;
}
if(dup2(fd, STDOUT_FILENO) == -1){ //输出重定向到/dev/null
//记录错误日志
return -1;
}
if(fd > STDERR_FILENO){
if(close(fd) == -1)
//记录错误日志
return -1;
}
return 1;
}
int main(int argc, char* const *argv){
if(ngx_daemon() != 1){
//创建守护进程失败,此处写失败日志等。
return -1;
}
else{
//创建守护进程成功,执行守护进程中要干的活
for(;;){
sleep(1);
printf("休息1秒,进程id = %d\n", getpid()); //此处打印无效果,标准输出已重定向到/dev/null
}
}
return 0;
}
Ss :小s表示进程leader
nginx的master进程也是守护进程,这个进程就是抄自nginx。
守护进程可以用命令启动,如果想开机启动,要系统初始化脚本启动。
4、守护进程不会收到的信号
4.1、SIGHUP信号
守护进程不会受到来自内核发送的信号。
另外的进程可以发SIGHUP信号,
作为通知信号,表示配置文件已经发生改动,守护进程应该重新读入。
sudo ./nginx -s reload 给已经启动的老master发送SIGHUP信号,
使用新配置启动新worker进程
跟kill -1 pid效果一样。 (看nginx源码)
4.2、SIGINT、SIGWINCH信号(来自内核发送的)
Ctrl+C,SIGWINCH(终端窗口大小改变信号)
具体用来干嘛?
5、守护进程和后台进程的区别
守护进程和终端无挂钩,但是后台进程是挂钩的,能往终端输出东西。
守护进程关闭终端不受影响,后台进程就会跟着退出。
脱离终端,不会屏蔽文件权限。
网友评论