一:线路规程
先给一个简单的栗子:
我们在终端下按下字母aaaaaa在bash下会显示aaaaa,但当我们按下组合键Ctrl-C,为什么却没有显示Ctrl-C呢?
这就是线路规程干的好事,那么什么是线路规程,简单点说就是就是内核层面的过滤器.
键盘输入的数据被驱动程序提交给线路规程,当输入的普通字符,线路规程不会做任何处理,默认让它通过,而当输入的是组合键时被解释成信号.这就很容易解释上面的现象.
二:shell分前后台控制的不是进程而是作业.?
1:jobs查看所有的作业
cat运行一个前台进程,cat& 把前台进程放到后台运行,我们再观察jobs此时作业的运行状态是stopped
2:fg 加上作业号,表明把几号作业放置前台
3:Ctrl+Z将前台作业Stop,然后bg 加上作业号表明将作业放置后台.
三:守护进程
:Linux系统启动时会启动很多系统服务器进程,这些系统服务器进程没有控制终端,不能直接集合用户交互,其他进程都是在用户登录会运行程序时创建,在运行结束或用户注销时终止,但系统服务进程不受用户登录注销的影响,它们一直在运行着.这种进程有一个名称叫守护进程.
简单点说守护进程
1:是不受用户登录(创建会话),和注销(销毁会话)的影响
2:与终端去关联
3:自成会话
创建守护进程的关键是setsid函数
调用setsid函数创建一个新的Session,并成为Session Leader.
#include<unistd.h>
pid_t setsid(void);
函数调用成功是返回新创建Session 的id(当前进程的id).出错返回-1.注意,调用这个函数之前,当前进程不允许是进程组的Leader,否则该函数返回-1, 要保证当前进程不是进程组的Leader很容易,先fork然后再调用setsid就可以了.fork创建的子进程和父进程在同一个进程组中,进程组的Leader必然是改组的第一个进程,所以子进程不可能是改组的第一个进程,在子进程找那个调用setsid就不会有问题.
创建守护进程
1:调用umask将文件模式创建屏蔽字设置为0;
2:调用fork,父进程退出
原因:
a:如果该守护进程是作为一条简单的shell命令启动时,那么父进程终止使得shell认为该命令已经执行完毕
b:保证子进程不是一个进程组的组长进程
3:调用setsid创建一个新会话.setsid会导致
a:调用进程成为新会话的首进程
b:调用进程成为一个进程组的组长进程
c:调用进程没有控制终端
4:将当前工作目录改为根目录
5;关闭不需要的文件描述符
6:忽略SIGCHLD信号
验证:
#include<stdio.h>
#include<unistd.h>
#include<signal.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/stat.h>
void mydaemon()
{
umask(0);
if(fork() >0)
{
exit(0);
}
else if(fork()<0)
{
return ;
}
setsid();
chdir("/");
close(0);
close(1);
close(2);
signal(SIGCHLD,SIG_IGN);
}
int main()
{
mydaemon();
while(1)
{
sleep(1);
}
return 0;
}
1:先进入proc查看守护进程
2:然后进程守护进程
3:我们再来查看文件描述符信息
创建守护进程fork()一次和fork()两次的区别?
第一次fork()的作用:
第一次fork的作用是让shell认为这条命令已经终止,不用挂在终端输入上,还有一个作用是为后面的setsid服务,setsid调用完后,子进程是会话组长又是进程组的组长,并且脱离控制终端
第二次fork()作用:
防止进程再次打开一个控制终端因为再次打开一个控制终端的前提条件是该进程必须是会话的组长,再fork一次,子进程id !=sid,所以无法打开新的控制终端;