linux 进程

来源:互联网 发布:enako 知乎 编辑:程序博客网 时间:2024/05/17 17:43
/*嵌入式,linux,进程,进程函数,进程的概念*/


>>多任务机制:
Linux允许用户在同一时间处理多个应用程序,这种机制称为“多任务”机制。


>>"多任务"的实现原理:
建立多个进程或线程,彼此之间可以独立运行不同的应用程序(也可以相互联系)。


>>进程分类:
1、交互式进程:与用户进行互动,及时响应用户的操作和命令(如监测鼠标键盘的进程、shell命令进程、文本编辑器等)。
2、守护进程:不与任何终端联系,一直在后台运行,一般在系统启动时开始执行,待系统关闭时才结束(如各类系统进程)。
3、批处理进程:不需要与用户进行及时互动,也不是系统运行所必须的,调度优先权很低,通常在后台运行(如数据搜索引擎、编译器等)。


>>进程组、会话:
1、进程组是一个或多个进程的集合,每个进程组都会有一个进程组长(组长进程ID=进程组ID,但进程组ID不会因组长进程的退出而收到影响)。
2、会话是一个或多个进程组的集合,会话的第一个进程组称为会话组长。


>>进程控制块:
1、对于多CPU的处理器来说,每个CPU可以运行不同的进程,这是真正意义上的“并行执行”。
2、实际应用中,进程数往往远多于CPU的个数,所以同一个CUP上各进程间实际上是按照时间片(一般是ms级)轮流执行的。
3、为了方便对进程的调度管理,所有进程的相关信息都被放在一个双向循环链表中(进程链表)。这个链表称为进程控制块(task_struct)。
4、进度块的内容很多,其中最重要的有两个段:进程状态(state)、进程标识符(pid)。


>>进程状态:
进程状态就是进程运行的阶段。可以分为三大类。
1、运行类状态:
1.1、正在运行。
1.2、即将开始运行:已经具备执行条件正在运行队列中等待内核调度——也称“就绪状态”。
2、阻塞类状态:
就是进程在“睡眠”,等待它所需要的资源可以满足其使用条件时,被“唤醒”进入运行状态。
2.1、可中断的阻塞状态:既能被显示地唤醒(一般调用wake_up系列宏)唤醒,又能被其他进程的信号唤醒(主动进入用sleep_on()函数)。
2.2、不可唤醒的阻塞状态:只能被指定的事件唤醒(如定时时间到、键盘有输入等),不能被其他进程的信号唤醒(主动进入用interruptible_sleep_on()函数)。
3、停止类状态:
3.1、暂停状态:当运行中的进程收到信号SIGSTOP、SIGTSTP、SIGTTIN或SIGTTOU时,就会进入暂停状态。暂停状态的进程收到信号SIGCONT就会转为运行状态。
3.2、僵死状态:子进程运行结束,父进程(由于父进程正忙、父进程已亡等原因)尚未使用wait函数族回收其退出状态。
创建当前进程的进程称为其父进程。当前进程称为子进程。一般来讲,子进程结束运行时要向父进程返回一些信息已供父进程使用。
3.3、消亡状态:子进程运行结束,父进程已回收其结束状态,这时子进程将会被彻底删除,进入消亡状态。
进程子创建时起,就在不同状态间进行转换,直至最终消亡。


>>进程标识符(PID:process identity):
1、进程标识符就是进程的身份证号,它唯一的标识一个进程(用getpid()获得)。
2、父进程标识符(PPID:parent process identity)(用getppid()获得)。
3、对进程的操作一般都通过进程标识符。

>>进程的创建函数fork():
1、在当前进程中调用fork()函数,就会创建一个新的子进程。当前进程自动成为新进程的父进程。
2、fork()创建的子进程是对父进程的复制(几乎是父进程的所有相关数据都后被子进程复制下来,包括程序执行的进度等)。
3、父子进程的区分是通过fork()函数的返回值:
返回0:是子进程。
返回正整数(子进程的ID):是父进程。
4、例程:
int main(void)
{
pid_t child1;
child1 = fork();
if(ciild1 == -1)
{
error handling;
exit(1);
}
else if(child1 == 0)
{
subprocess program;
}
else
{
parentprocess program;
}
exit(0);
}
说明:
4.1、子进程一旦创建就会进入执行状态,进而和父进程竞争CUP的执行时间片(内核通过进程控制块来调度协调,用户也可根据需要调整父子进程间的执行顺序,如使父进程阻塞等手段)。
4.2、子进程从child1==0条件下开始执行,父进程从else下开始执行,两者并行(轮流获得CPU的执行权)。


>>子进程执行新程序的函数族exec
既然子进程时父进程的复制品,那么子进程存在的价值是什么呢?可以通过调用exec函数族来使子进程执行新的程序(一个典型的应用就是父进程监测标准输入,一旦有命令就创建一个子进程去响应,父进程本身继续监测)。
cexc函数族有6个原型(只有execve才是系统调用,其他都是在其基础上进行的二次封装):
1、int execl(const char *path, const char *arg, ......);
2、int execle(const char *path, const char *arg, ...... , char * const envp[]);
3、int execv(const char *path, char *const argv[]);
4、int execve(const char *filename, char *const argv[], char *const envp[]);
5、int execvp(const char *file, char * const argv[]);
6、int execlp(const char *file, const char *arg, ......);
以上函数族成功都返回文件的当前读写位置,失败返回-1。
根据函数名第5、6位的不同可以分为三类:
1、文件的查找方式不同:
有“P”时,只给出文件名即可;
无“P”时,要给出文件的“全路径名”。
2、命令行参数给出方式不同:
“v”,以数组指针形式给出(具体参数存储在指针指向的数组中)。
“l”,以列表方式给出参数;
3、环境变量的引用方式不同:
有“e”时,以数组指针形式给出(具体参数存储在指针指向的数组中);
无“e”时,默认引用当前环境变量。
例如:execve();用户给出执行文件的“全路径名”,以数组指针的方式给出所有执行参数,用户给定所有环境变量,所以只有execve才是基本函数。
使用exec函数族有两点需要注意:
1、无论以何种方式给出参数与环境变量,这两者都应以“NULL”结尾。
2、exec函数族的调用很容易失败,使用时一定要进行失败检查。

>>进程的退出:
1、exit()函数与return语句的区别:
return语句只是返回当前执行的函数(回到调用当前函数的母函数中继续执行)。
而exit()函数是退出整个进程(一般是退出一个完整的程序,可能包含多个函数的全部退出)。
2、exit()与_exit()的区别:
exit()是正常的进程退出,它要清理用户的I/O缓冲,吧用户缓冲区内的内容写回文件,并关闭所有打开的文件。
_exit()是暴力退出,什么都不处理,直接退出调用它的进程。
比如:标准输出采用行缓冲,遇到换行符"\n"时才会将缓冲区内容写入终端进行输出显示等。
一个没有换行符的printf("abc");语句,当遇到exit();时仍然会显示出来,而遇到_exit();就直接掉丢不会显示了。
3、参数的含义:
exit()与_exit()的参数都是整数,用以向父进程传递退出原因。参数0表示正常退出,其他数值对应各种错误(由用户定义,可以用正整数表示警告退出,负整数表示错误退出)。

>>进程的回收:
有些进程不是运行完了就算了,是要向父进程返回一些结果的。当然,父进程也可能“主动等待”子进程返回数据,这时候需要调用wait()函数族。
wait()是waitpid()的一个特例。
1、pid_t wait(int *status);
功能:阻塞父进程(调用其的进程),直到一个子进程结束或者父进程接到一个指定的信号为止。
返回值:成功返回第一个结束的子进程ID;失败返回-1(没有尚未结束的子进程)。
参数:status指向一个用来保存子进程结束时状态的整形对象。
2、pid_t waitpid(pid_t pid, int *status, int options);
功能:
返回值:>0表示已结束运行的子进程ID;0表示使用选项WNOHANG且没有子进程结束;-1出错(并设置errno)。
参数pid:>0表示待回收的子进程ID;=0表示回收同组的任意一个子进程;=-1表示回收任何一个子进程(此时等同于wait()函数);<-1表示回收进程组号等于-pid的任意子进程。
参数status:同wait()。
参数options:=WNOHANG表示若没有子进程结束,也不阻塞父进程,而是立即返回0;=WUNTRACED返回已暂停但尚未报告的子进程状态。
3、如果一个子进程已经结束,但父进程还没有调用wait()函数族来对其进行回收,那么这个子进程的结束状态将会被保留,此时子进程就变成了一个“僵尸进程”(未完全死掉)。

>>守护进程(daemon):
1、守护进程不受用户、终端或者其他变化的影响(用户可以把一个普通进程变成守护进程)。
2、linux的很多系统服务都是通过守护进程实现的。
3、编写守护进程需要5步:
1>创建子进程,父进程退出
此时子进程已经摆脱了父进程的管控,成为了“孤儿进程”,系统检测到孤儿进程会将其作为1号进程(init进程)收养。
2>在子进程中创建一个新会话(调用setsid()函数)
由于子进程从父进程那里继承了会话、进程组和控制终端,为了摆脱这些对子进程的控制,需要创建一个新的会话来摆脱它们。
3>改变当前目录(调用chdir()函数)
由于子进程的存在,其所在的文件系统可能无法卸载(比如子进程从属于/mnt/usb等),所以需要将当前目录改为根目录"/"或者临时目录"/tmp"。
4>重设文件权限掩码(调用umask(0)函数)
子进程从父进程那里继承来的文件权限可能是只读,这样对子进程的后续操作带来了隐患(文件的实际权限=创建权限-掩码权限)。
5>关闭文件描述符
如果父进程里已经打开了没写文件,子进程也一并将其继承,而这些打开的文件对子进程来说可能是一种多余(这些打开的文件也会导致所在的文件系统不能被卸载),需将其关闭。
for(i=0; i<MAXFILE; i++)
{
close(i);
}


>>进程间的通信概述:
1、管道进行通信
有名管道:可以在本地的任何进程间进行通信。
无名管道:只能在有亲缘关系的管道间进行通信(父子进程间、兄弟进程间)。
2、共享内存
是最高效的进程间通信方式,需要考虑同步与互斥问题。
3、其他进程间的通信方式
消息队列、信号量、信号、套接字(用于网络通信)。

阅读全文
'); })();
0 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 毕业设 本科毕业学位是什么 研究生毕业要求 成人应届本科毕业生 毕业多久算应届毕业生 以毕业为主题的画 女朋友毕业送什么花 朋友毕业送什么花 毕业送什么花好 毕业礼送什么花 儿子毕业典礼送什么花 毕业送什么花给同学 男朋友毕业送什么花 男生毕业送什么花 毕业典礼送什么花 毕业证图片 学历证书毕业证 毕业证照片 毕业证查询系统 高中毕业证查询 初中毕业证图片 假毕业证 大学毕业证图片 成考本科毕业证 毕业证在线制作 成人中专毕业证 毕业证模板 毕业证掉了 毕业证扫描件 毕业证什么时候发 湖北毕业证 毕业证号是什么 广西毕业证 做毕业证 毕业证重要吗 毕业证大小 毕业证查 毕业证有用吗 北京大学毕业证 毕业证类型 毕业证证明