任督二脉之进程管理(2)

一、第二次课大纲
1.fork、vfork、clone
2.写时拷贝技术
3.Linux线程的实现本质
4.进程0和进程1
5.进程的睡眠和等待队列
6.孤儿进程的托孤,SUBREAPER
1.fork、vfork、Copy-on-Write例子
2.life-period例子,实验体会托孤
3.pthread_create例子,strace它
4.彻底看懂等待队列的案例

二、fork

1)fork创建一个进程。p1是一个task_struct,p2也是一个task_struct,调度器只通过task_struct来调度进程。在p1中fork后新进程p2,直接完全对拷给p2的task_struct,两者完全一样(当然pid不同),资源一样。只要有修改就不一样了,资源分裂。比如fs,fd等。chdir函数修改cwd。

2)但是内存资源mm不好分裂。采用写时拷贝技术(COW)

例子:

 1 #include <sched.h>
 2
 3 #include <unistd.h>
 4
 5 #include <stdio.h>
 6
 7 #include <stdlib.h>
 8
 9
10
11 int data = 10;
12
13
14
15 int child_process()
16
17 {
18
19     printf("Child process %d, data %d\n",getpid(),data);
20
21     data = 20;
22
23     printf("Child process %d, data %d\n",getpid(),data);
24
25     _exit(0);
26
27 }
28
29
30
31 int main(int argc, char* argv[])
32
33 {
34
35     int pid;
36
37     pid = fork();
38
39
40
41     if(pid==0) {
42
43         child_process();
44
45     }
46
47     else{
48
49         sleep(1);
50
51         printf("Parent process %d, data %d\n",getpid(), data);
52
53         exit(0);
54
55     }
56
57 }

运行结果:

下面是COW详细过程:fork后父子进程的页表完全一样,但是只有RD_ONLY,其中一个进程P2修改数据,那么就申请一个新的物理页面,把原页面数据拷贝到新的物理页面,再修改P2进程页表。

3)从上面可以看出,COW技术依赖于MMU(硬件),那么没有MMU的系统,比如uclinux,不能执行COW,没有fork函数,只有vfork。vfork会阻塞父进程(子进程调用_exit,exec之一才返回)。所以vfork后P1和P2的mm指针指向同一个地址。

vfork后P1和P2的mm指针指向同一个地址。

例子:

 1 #include <sched.h>
 2
 3 #include <unistd.h>
 4
 5 #include <stdio.h>
 6
 7 #include <stdlib.h>
 8
 9
10
11 int data = 10;
12
13
14
15 int child_process()
16
17 {
18
19     printf("Child process %d, data %d\n",getpid(),data);
20
21     data = 20;
22
23     printf("Child process %d, data %d\n",getpid(),data);
24
25     _exit(0);
26
27 }
28
29
30
31 int main(int argc, char* argv[])
32
33 {
34
35     int pid;
36
37     pid = vfork();
38
39
40
41     if(pid==0) {
42
43         child_process();
44
45     }
46
47     else{
48
49         sleep(1);
50
51         printf("Parent process %d, data %d\n",getpid(), data);
52
53         exit(0);
54
55     }
56
57 }

运行结果:

那么可以放大,把各种资源全部指向同一个地址,资源全部共享。也即pthread_create(其调用了clone函数,再共享其他资源),这就是轻量级进程,即线程。

4)也可以只共享部分资源,clone函数的参数指定。既不是进程也不是线程。

5)PID和TGID

以上fork,vfork,clone都会产生新的task_struct,有独立的pid。POSIX要求一个进程里面有多个线程,必须对外表现为一个整体,getpid时是同一个值。linux就增加一个TGID=P1。

例子:

 1 #include <stdio.h>
 2 #include <pthread.h>
 3 #include <stdio.h>
 4 #include <linux/unistd.h>
 5 #include <sys/syscall.h>
 6
 7 static pid_t gettid( void )
 8 {
 9
10     return syscall(__NR_gettid);
11
12 }
13
14 static void *thread_fun(void *param)
15 {
16
17     printf("thread pid:%d, tid:%d pthread_self:%lu\n", getpid(), gettid(),pthread_self());
18
19     while(1);
20
21     return NULL;
22 }
23
24 int main(void)
25 {
26     pthread_t tid1, tid2;
27     int ret;
28
29     printf("thread pid:%d, tid:%d pthread_self:%lu\n", getpid(), gettid(),pthread_self());
30     /*getpid():TGID, gettid():内核空间的pid,pthread_self(): 用户空间thread库里的id*/
31
32
33     ret = pthread_create(&tid1, NULL, thread_fun, NULL);
34
35     if (ret == -1) {
36
37         perror("cannot create new thread");
38
39         return -1;
40
41     }
42
43     ret = pthread_create(&tid2, NULL, thread_fun, NULL);
44     if (ret == -1) {
45         perror("cannot create new thread");
46         return -1;
47     }
48
49     if (pthread_join(tid1, NULL) != 0) {
50         perror("call pthread_join function fail");
51         return -1;
52     }
53
54     if (pthread_join(tid2, NULL) != 0) {
55         perror("call pthread_join function fail");
56         return -1;
57     }
58
59     return 0;
60 }

top命令看到的多线程进程是一个整体,top -H就是线程视角,也可以运行top后按H转换视角。

pstree:

进程视角:

线程视角:

三、subreaper和托孤

subreaper:通过系统调用设置自己为subreaper,pstree里面显示为init的为subreaper。

在进程退出后会在父子关系树向上找sbureaper,把子进程托孤给它,找不到sbureaper看托孤给init进程。

例子,托孤:先pstree观察父子进程在树形结构中的位置,然后把父进程杀掉,pstree观察子进程在树形结构中的位置变化。

 1 #include <stdio.h>
 2 #include <sys/wait.h>
 3 #include <stdlib.h>
 4 #include <unistd.h>
 5
 6 int main(void)
 7 {
 8     pid_t pid,wait_pid;
 9     int status;
10
11     pid = fork();
12     if (pid==-1) {
13         perror("Cannot create new process");
14         exit(1);
15     } else     if (pid==0) {
16         printf("child process id: %ld\n", (long) getpid());
17         pause();
18         _exit(0);
19     } else {
20         printf("parent process id: %ld\n", (long) getpid());
21         wait_pid=waitpid(pid, &status, WUNTRACED | WCONTINUED);
22         if (wait_pid == -1) {
23
24             perror("cannot using waitpid function");
25             exit(1);
26
27         }
28
29         if(WIFSIGNALED(status))
30             printf("child process is killed by signal %d\n", WTERMSIG(status));
31
32         exit(0);
33     }
34 }

三、睡眠:深度睡眠VS浅度睡眠

睡眠的实现:关键--等待队列(类似设计模式中的观察者模式),等待资源的进程加入等待队列,资源到来后唤醒等待队列不会唤醒单个进程。看globalfifo代码:https://github.com/21cnbao/process-courses/blob/master/day2/globalfifo.c

四、进程0和1

1号进程的父进程pid=0。但是pstree里面看不到0号进程,实际上0号进程创建完init进程后就退化为idle进程,也就是其他进程都不用cpu的情况下才运行,也即调度优先级最低,进入睡眠状态WFI,省电。设计的好处:每个进入进入睡眠之前就查一下是不是最后一个进程,是的话就置为WFI低功耗,这样就耦合到了每个进程里面;idle的设计就没有耦合了。

 1 [email protected]:~/vmware-tools-distrib$ cat /proc/1/status
 2 Name:    systemd
 3 State:    S (sleeping)
 4 Tgid:    1
 5 Ngid:    0
 6 Pid:    1
 7 PPid:    0
 8 TracerPid:    0
 9 Uid:    0    0    0    0
10 Gid:    0    0    0    0
11 FDSize:    256
12 Groups:
13 NStgid:    1
14 NSpid:    1
15 NSpgid:    1
16 NSsid:    1

五、问答

1、进程0是天上掉下来的,是从boot跑到linux。???????也是有task_struct的。

2、vfork阻塞父进程,子进程一般是创建后执行exec。
3、多线程的进程,/proc/tgid/task/pid。

4、MMU原理,数据结构

http://ytliu.info/blog/2014/11/24/shi-shang-zui-xiang-xi-de-kvm-mmu-pagejie-gou-he-yong-fa-jie-xi/

原文地址:https://www.cnblogs.com/shihuvini/p/8414099.html

时间: 2024-07-30 09:44:24

任督二脉之进程管理(2)的相关文章

任督二脉之进程管理(1)

进程生命周期,进程生命周期创建.退出.停止,以及僵尸进程是什么意思. 一.进程的定义 进程--线程.进程是资源分配单位:搞清楚进程就是搞清楚进程资源情况.进程控制块PCB是OS的通用叫法.task_struct结构体描述进程的资源情况.如下图所属: 1)*mm描述内存资源 2)*fs:文件系统资源 3)文件资源:注意与fs的区别,打开文件的fd数组fd_array记录打开文件的fd 4)*signal:该进程的信号处理函数(用户理解为多态) 5)pid:数量有限 节选自<linux操作系统原理与

案例干货|用友罗涛:打通产品开发的任督二脉

[精彩预告]用友集团开发管理部总经理罗涛将于5月21日在上海MPD工作坊进行<破解4小时上线传说>的3小时分享.通过一个故事引入互联网+产品开发的迭代思路.价值发掘和发布规划等核心思想和工具,将结组利用小图团队的力量使用影响地图.用户故事地图.无代码验证等演练手段在3个小时的工作坊内快速发布一个产品,带领学员在操作中理解精益和敏捷.文章来源:公众号 :msup(ID:msupclub)关注回复“体验工坊”有惊喜. 导读:在面对需求的变化无常.人员的变动和技术的更新时,对客户价值的识别尤其重要,

打通电商多模式支持的“任督二脉”

你听说过任督二脉吗?像这样~ 咳咳~今天不讲武功,讲电商平台设计的功夫~ 背景 当今的电商可不仅仅是B2C商城,接下来还会有O2O,往后可能还会有商超.奥莱.二手交易...且称之为业务模式~而每个业务模式下还会有预售.竞拍.拼团等不同组合的子模式. 可是我商城的商品列表页不想展示O2O的商品啊,商品列表的数据希望按一定规则相互隔离.其他模块,有的出于操作习惯的考虑不隔离,有的出于用户行为的考虑需要隔离. 各模块数据隔离需求如下   列表页 商详页 商品组 优惠券 活动 订单 ... 原商城 隔离

K2 BPM_当K2遇上医药,用流程打通企业的任督二脉_业务流程管理系统

据调查,如今仍有60%的医药企业,存在合规经营和利润下降的困扰,在“研”.“产”.“供”.“销”的运营过程中,时时伴随着严苛的管理政策和法规.如何加强企业跨部门.跨组织.跨业务线的执行能力,始终是管理层最关注的话题.而流程,则是打通“任督二脉”,提高执行力的最佳解决办法. 当K2遇上医药 K2在医药行业的核心应用 -医疗推广活动管理 -讲者管理 (含讲者资质审核/讲者在线付款流程) -全面费用管理 -经销商管理 -特价及返利管理 -医疗问询及不良反应记录追踪 -招投标管理 -注册证管理 -销售&

天河微信小程序入门《三》:打通任督二脉,前后台互通

原文链接:http://www.wxapp-union.com/forum.php?mod=viewthread&tid=505&extra=page%3D1 天河君在申请到https证书后就第一时间去部署后台环境,但是发现每次访问https都要带上8443端口实在是很坑爹啊,作为一个强迫症晚期,我要做的自然是不带端口直接访问.打开你tomcat下的conf文件夹,编辑里面的server.xml <Connector port="80" protocol=&quo

打通任督二脉---原来这就是计算机(持续更新)

笔者是一个计算机爱好者,还记得当初还是个刚上小学的孩子,那时,我第一次听说世界上还有计算机这种东西(那时都叫电脑),当时是90年代,估计那时全村也没有一个人见过电脑,所以电脑就被传的神乎其神:有了电脑,任何犯人都逃不过警察的追捕,因为电脑能算出来犯人在哪里,电脑能一瞬间算出当时觉得比登天还难的5位数的加减乘除,电视里的天气预报也是电脑算的,什么火箭,卫星,原子弹,氢弹都是电脑算出来的......  能想象出我当时对电脑崇拜的心情吗,当时,在我的眼里,电脑不是机器,而是像神一样的虚幻的存在,甚至都

任督二脉

RMI:https://www.cnblogs.com/xt0810/p/3640167.html 因为真要有技术深度的话,你可能需要花费至少2年的时间,从底层开始研究一些基础性的技术. 在打通你的底层技术任督二脉之后,再去对常见的开源技术进行深入的源码研究,比如说:dubbo.zookeeper.spring cloud.redis.rocketmq.elasticsearch,等等. 有了几年的积累过后,最后你在面试的时候,技术深度的体现,其实都是厚积薄发的. 原文地址:https://ww

二十一、进程管理之一基本概念

  硬件 调用.调用接口.库调用 线性内存地址空间.物理内存地址空间.线性地址.物理地址 交换内存:缺页异常 进程内存结构 常驻内存集.虚拟内存集 进程.进程元数据.结构体.任务结构体.链表 进程类型.状态(read,runing,sleep,stopped,zombie) 可中断睡眠.不可中断睡眠 创建子进程的过程  进程优先级.进程调度.进程队列 过期队列:抢占式多任务.系统调用IO IO模型.系统调用IO等待过程 进程间通信:IPC 硬件 编程接口: syscall(系统调用) libca

打通MySQL架构和业务的任督二脉

目前,在很多OLTP场景中,MySQL数据库都有着广泛的应用,也有很多不同的使用方式.从数据库的业务需求.架构设计.运营维护.再到扩容迁移,不同的MySQL架构有不同的特点,适应一定的业务场景,或者解决一定的业务问题. DBA作为数据库架构的设计.实施.维护人员,不仅要对各种MySQL架构非常熟悉,还要了解业务,对于不同的业务有一定的划分和认识,并根据业务特点和架构特点,合理选择和使用MySQL,满足业务需求. 本文从MySQL常见架构.业务环境分类.业务与架构结合使用原则三个方面对MySQL数