进程的几种重要状态,就绪态;运行态;僵尸态;等待态(浅度睡眠、深度睡眠);停止态。
就单核CPU而言,在同一时间只能运行一个进程,但实际上要运行的进程不止一个,系统中又两个链表:就绪态链表和进程链表。
就绪态,只差cpu调用就能运行的状态。
运行态,得到cpu时间的就绪进程。
僵尸态,进程结束,等待父进程回收内存。
等待态,等待一定条件,满足后就能到达就绪态,现在就算被cpu调用也运行不了。浅度睡眠的时候,进程可以被信号唤醒;深度睡眠等待时,不能被唤醒,只能在满足条件的情况下才会结束睡眠。
等待态,暂停并不是进程终止,只是被信号暂停了,可以被恢复。
本质上是为了高效的使用CPU,跑不了的就交出CPU进行等待,让CPU去无时无刻的干活。
system函数是原子级操作,本质上作用与eyec+fork实现的功能差不多,只是eyec+fork是非原子级的操作,而system是原子操作。
原子操作,不会引来竞态,坏处就是连续占用CPU时间过长。不必要的原子操作,影响实时性,在不可避免的使用原子操作时,应尽可能减少占用时间。
system支持PATH,在环境变量中查找变量。
进程关系,①无关系;②父子进程关系;③进程组;④会话。无关系进程间是严格分隔的。父子进程,是父fork子。
进程组(group),组操作,组用户等,是对权限位而言的,进程组由多个进程组成,组长ID为组ID,希望某些进程关联更高,相互能够有交流、共享。
会话,进程组的组(session)。
守护进程是用户进程,基于应用层,而非应用层。守护进程的特点①daemon守护进程,后台程序(d)。②长期运行(开机到关机)。③与控制台脱离,不予控制台终端绑定。④服务器(server)一直运行可以提供基础服务,如nfs,shell当需要使用时与程序服务器通信,提供服务,一般以守护进程的方式实现。
常见的守护进程,syslogd斯特日志守护进程提供syslog(日志);cron时间管理如定时执行管理。任意的一个进程都可以成为守护进程,步骤如下:
①子进程等待父进程退出。
②子进程使用setsid创建新会话期,脱离控制台。
③调用chdir将当前工作目录设定到/
④umask设为0,以取消任何文件的权限。
⑤关闭所有文件描述符。
⑥将fd的0、1、2定位到/dev/null。
create_daemon(){
......
pid=fork();
if(pid<0)
{
perror("fork1");
}
if(pid>0)
{
exit(0);
}
if(0==pid)
{
pid=setsid();//设为新的会话期,脱离控制台
if(pid<0)
{
perror(“setsid”);
exit(-1);
}
chdir("/");//工作目录设在根目录
umask(0);
for(int i=0;i<xxx;i++)//遍历到系统许可的最大文件数目,目的是不让这个进程去一直占用某个文件
{
close(i);//用sysconf()得到xxx是多少,int cnt=sysconf(_SC_OPEN_MAX)
}
open("/dev/null",O_RDWR);//fd=0标准输入
open("/dev/null",O_RDWR);//fd=1标准输出
open("/dev/null",O_RDWR);//fd=2标准错误
//将三个标准指向垃圾堆,此后该进程再无任何标准入/出/err
}
}
使用kill -9 xxx使用9号信号(结束),结束xxx守护进程。