【7】linux进程管理-2-3

上传人:kms****20 文档编号:51754744 上传时间:2018-08-16 格式:PPT 页数:66 大小:1.85MB
返回 下载 相关 举报
【7】linux进程管理-2-3_第1页
第1页 / 共66页
【7】linux进程管理-2-3_第2页
第2页 / 共66页
【7】linux进程管理-2-3_第3页
第3页 / 共66页
【7】linux进程管理-2-3_第4页
第4页 / 共66页
【7】linux进程管理-2-3_第5页
第5页 / 共66页
点击查看更多>>
资源描述

《【7】linux进程管理-2-3》由会员分享,可在线阅读,更多相关《【7】linux进程管理-2-3(66页珍藏版)》请在金锄头文库上搜索。

1、上次内容 虚拟空间=内核空间+进程空间 进程控制块 进程队列组织后面实验调整为每周五都上1进程控制块2查2.4内核: struct task_struct struct list_head run_list; struct task_struct *next_task, *prev_task; struct task_struct *p_opptr, *p_pptr, *p_cptr, *p_ysptr, *p_osptr; struct task_struct *pidhash_next;struct task_struct *pidhash_pprev; 3当前进程pcb在内核 栈底端 内

2、核定义current宏 可方便找到它: esp 偏移8K= 8192内核内核栈8k task_structESPtask_struct init_tasktask_structtask_structtask_structtask_structtask_structprev next45查找某个进程 init_task链表 与运行相关current散列表 u struct task_struct *pidhashPIDHASH_SZ u find_task_by_pid(PID) u 冲突时:*pidhash_next;6三、进程创建、终结及相关系统调用1.进程状态 可运行态 u运行 u就绪 睡

3、眠(等待)态 u浅度:等待资源有效时,被信号或时钟中 断唤醒 u深度:不能由其他进程通过信号和时钟中 断唤醒 暂停态:暂时停止接受某种处理如程序调试(挂 起) 僵死态:执行接受但尚未消亡,尚未释放pcb7Linux进程状态及转换 fork()TASK_RUNNING 就绪TASK_INTERRUPTIBLE 浅度睡眠TASK_UNINTERRUPTIBLE 深度睡眠TASK_STOPPED 暂停TASK_ZOMBIE 僵死占有CPU 执行do_exit()schedule()ptrace()schedule()当前进程 时间片耗尽等待资源到位 sleep_on() schedule()等待资源

4、到位 interruptible_sleep_on() schedule()资源到位 wake_up_interruptible() 或收到信号 wake_up()资源到位 wake_up()收到信号 SIGCONT wake_up()82.进程的创建传统方法单一函数: 创建进程地址空间;读入可执行文件;开始 执行UNIX分创建和执行两步: fork函数:复制当前进程创建子进程(快速 创建的特点) exec函数:读取可执行文件并载入进程地址 空间执行9linux“写时复制 ”技术 fork()与以往不同,不是全部复制进 程空间,实际开销只是复制父进程的 页表以及给子进程创建唯一的PCB。 父进

5、程的资源被设置为只读(父进程 页面被置上写时保护位),当父进程 或子进程试图修改某些内容时,内核 才在修改前将该部分进行拷贝写 时复制。pcb1程序1 父进程 fork页表1pcb2页表2无论谁写时,才 复制要写的页面10进程/线程创建函数:fork()/clone() 实际上都是调用内核函数do_fork(),其主要操作为: 调用alloc_task_struct( )函数获得8KB的union task_union内存区,用来存放新进程的PCB和内核栈。 让当前指针指向父进程的PCB,并把父进程PCB的内容 拷贝到刚刚分配的新进程的PCB中。 检查新创建这个子进程后,当前用户所拥有的进程数

6、 目没有超出给他分配的资源的限制。 现在,do_fork( )已经获得它从父进程能利用的几乎 所有的东西;剩下的事情就是集中建立子进程的新资 源,并让内核知道这个新进程已经呱呱落地。11接下来,子进程的状态被设置为TASK_UNINTERRUPTIBLE 以保证它不会马上投入运行。 调用get_pid()为新进程获取一个有效的PID。 开始组织关系 更新不能从父进程继承的PCB的其他所有域,例如, 进程间亲属关系的域。 把新PCB插入进程链表,确保进程之间的亲属关系。 把新PCB插入pidhash哈希表。 把子进程PCB的状态域设置成TASK_RUNNING,并调用 wake_up_proce

7、ss()把子进程插入到运行队列链表。 让父进程和子进程平分剩余的时间片。 返回子进程的PID,该PID最终由用户态下的父进程读取一次调用,两个 PID返回值12133.进程执行功能 fork调用后,出现两个进程执行,父子进程几乎 完全一样,新的子进程如何执行自己的代码功能? 以简化的shell框架为例: while(true) read_command(command,parameters); if(fork!=0)/*父进程*/ wait(NULL); else/*子进程*/ exec(command,parameters,0); 14 exec函数族包括若干函数,作用是根据 文件名找到相应

8、的可执行文件。 u 子进程的地址空间被填入可执行文件的 内容,其进程功能开始有别于父进程 u exec函数执行成功就会进入新进程执行 不再返回。 u exec调用失败才返回-1,继续在克隆来 的地址空间中从调用点向下执行15 并发顺序 u fork后,父子进程并发执行,linux会优先调度 执行子进程。因为,子进程创建后就调exec载入可 执行文件内容,而之前如果父进程进行了写时复制 就会成为额外开销。 关于写时复制 u 如果先调父进程 u 因为fork将父进程资源设为只读,只要父进程 进行修改,就要开始“写时复制”,把父进程要改的 页面复制给子进程(写子空间)。 u 继续运行,一旦子进程被调

9、度到,它要用exec 载入另一个可执行文件的内容到自己的空间(又写 子空间),可见上步的写入就多余了。 所以,fork后优先调度子进程是为了从父进程 克隆到子进程后,尽量减少没必要的复制。164.进程的终结 进程结束: u调用exit或在main函数中return(主动 ) u被信号和异常终结(被动) 终结时进程要释放其占用的资源并报告 给父进程。都是通过系统调用靠内核函数 do_exit()完成。 u回收与进程相关的各种内核数据结构, 设置状态为僵死TASK_ZOMBIE u将其所有子进程托付给init进程 u调用schedule函数,选择一个新进程运 行。17void exit(int s

10、tatus); 可利用参数status传递进程结束时的状态 调用exit后的进程不是马上消失,而是变为僵 尸状态,放弃了几乎所有内存空间,不再被调 度,但保留有pcb信息供wait收集,包括:u 正常结束还是被退出 u 占用总系统cpu时间和总用户cpu时间u 缺页中断次数,收到信号数目等18 分析下面程序中的“僵尸” #include #include main() pid_t pid; pid=fork(); if (pid0) /*父进程 sleep(60); wait(NULL);子进程一被调度到即 结束成僵死态。谁来 回收其pcb?父进程被调度执行到最后,也会隐 式结束成僵死态。谁来

11、回收其pcb?父进程调用wait函数收集僵死 态子进程的pcb信息,将其彻 底销毁后返回执行: gcc o mywait mywait.c ./mywait pc=fork(); if (pc0) /*父进程 pr=wait(NULL); printf(“catch a child process with pid of %dn”,pr(); exit(0); #include #include #include #include 22 wait起到了同步的作用,父进程只有当子进程 结束后才能继续执行。 子进程退出时的状态会存入wait的整型参数 status中。由于相关信息在整数的不同二进制

12、 位上,wait收集相关信息是是利用定义的一套 专门的宏。23进程生命周期中的系统调用 Fork()父亲克隆一个儿子。执行fork()之后,兵分两路 ,两个进程并发执行。 Exec()新进程脱胎换骨,离家独立,开始了独立工作的 职业生涯。 Wait()等待不仅仅是阻塞自己,还准备对僵死的子进程 进行善后处理。 Exit()终止进程,把进程的状态置为“僵死”,并把其 所有的子进程都托付给init进程,最后调用schedule()函 数,选择一个新的进程运行。 24进程的一生进程的一生 随着一句fork,一个新进程呱呱落地,但这 时它只是老进程的一个克隆。然后,随着exec,新 进程脱胎换骨,离家

13、独立,开始了独立工作的职业 生涯。 人有生老病死,进程也一样,它可以是自然 死亡,即运行到main函数的最后一个“,从容地 离我们而去;也可以是中途退场,退场有2种方式 ,一种是调用exit函数,一种是在main函数内使用 return,无论哪一种方式,它都可以留下留言,放 在返回值里保留下来;甚至它还可能被谋杀,被其 它进程通过另外一些方式结束它的生命。 进程死掉以后,会留下一个空壳,wait站好 最后一班岗,打扫战场,使其最终归于无形。这就 是进程完整的一生。25实验二 练习课本中fork、wait、exit中的程序, 记录问题并分析。 实验下页程序,运行若干次,给出打印 结果表现的父子并

14、发顺序的说明;去掉 sleep语句又是什么执行顺序?试分析。 找资料,尝试做个使用fork、exec函数 族函数的小程序。262.给出尽量多的测试结果并进行分析 。 int main(void) pid_t pid;char *message;int n;pid = fork();if (pid 0; n-) printf(message);sleep(1); return 0;#include #include #include #include 3.exec举例27多个子进程 分析试试看修改不同的位置,根据执行效果试着 分析并发顺序 程序后台执行中用“kill -9 pid号” 结 束子进

15、程试试看结果如何 waitpid参数0换成后面的标志如何gcc o mywait mywait.c ./mywait p = clone( 0, flags | CLONE_VM ); if ( p ) /* 父*/ return p; else /* 子*/ fn(arg);exit( ); 31几个特殊身份的几个特殊身份的内核线程内核线程1.没事闲逛的0号进程(线程) p 从无到有诞生的第一个内核线程,由start_kernel函 数完成内核初始化时创建。 p 执行cpu_idle()函数(省电减热),它的PCB就是 init_task。没有其他进程可调度时,才选择进程0。 2.1号进程i

16、nit(线程) 初始化阶段如下创建: kernel_thread(init,NULL,CLONE_FS|CLONE_FILES|CLONE_SIGHAND) p 传递给clone的参数表示0号线程和1号线程共享文件 系统、打开文件、信号处理程序。 p 该init内核线程被调度到时,执行内核函数init(), 常规内核任务初始化若干内核线程32u用户态第1个进程init的产生 u1号内核线程的init内核函数中调用 execve(),装入用户态下的可执行程序 sbin/init,内核线程变为用户进程。 uinit进程从不终止,负责创建和监视操作 系统外层所有进程的活动。33四、进程调度对系统的总体设计、系统实现 、功能设置以及各个方面的性能都有决定 性影响。 考虑系统实现的复杂程度在功 能和性能方面常要做出

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 生活休闲 > 科普知识

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号