Linux系统编程——09-linux-day05(进程控制)

在学习Linux系统编程总结了笔记,并分享出来。有问题请及时联系博主:Alliswell_WP,转载请注明出处。

09-linux-day05(进程控制)

 

 

一、学习目标

1、了解进程相关的概念

2、掌握fork/getpid/getppid函数的使用

3、熟练掌握ps/kill命令的使用

4、熟练掌握execl/execlp函数的使用

5、说出什么是孤儿进程什么是僵尸进程

6、熟练掌握wait函数的使用

7、熟练掌握waitpid函数的使用

 

二、进程

1、进程和程序

什么是程序?编译好的二进制文件。

什么是进程?运行着的程序。

  站在程序员的角度:运行一系列指令的过程。

  站在操作系统角度:分配系统资源的基本单位。

区别:

  程序占用磁盘,不占用系统资源。

  进程占用系统资源。

  一个程序对应多个进程,一个进程对应一个程序。

   程序没有生命周期,进程有生命周期。

 

2、单道和多道程序设计

 

3、进程的状态转化

进程的状态切换

 

4、MMU 的作用

》MMU作用:1)虚拟内存和物理内存的映射;2)修改内存访问级别

用户空间映射到物理内存是独立的。

 

5、PCB的概念

Linux内核的进程控制块是task_struct结构体。

查找结构体:

> sudo grep -rn "struct task_struct {" /usr/

技巧:光标停留在{上,按%,可以到结构体的结尾。(400多行)

查看进程的资源上限:

>ulimit -a

 

6、获取环境变量

查看所有的环境变量:(写法:key=value,且等号两端不能有空格)

>env

常见的环境变量:

>echo $HOME

>echo $PATH

 

》getenv函数——获取环境变量

man 2 getenv

char *getenv(const char *name);

>touch getenv.c

>vi getenv.c

1 #include<stdio.h>
2 #include<stdlib.h>
3 
4 int main()
5 {
6     printf("homepath is [%s]\n", getenv("HOME"));
7     return 0;
8 }

>make

>./getenv

》setenv函数——设置环境变量的值

man 2 setenv

int setenv(const char *name, const char *value, int overwrite);

  参数overwrite取值:1-覆盖原环境变量;0-不覆盖(该参数常用于设置新环境变量。)

一般配置(.bashrc)文件!(如:export key=val;)

》unsetenv函数——删除环境变量name的定义

man 2 unsetenv

int unsetenv(const char *name);

  注意事项:name不存在仍返回0(成功),当name命名为“ABC=”时则会出错!

 

7、进程控制函数fork

>touch fork.c

>vi fork.c

 1 #include<stdio.h>
 2 #include<unistd.h>
 3 
 4 int main()
 5 {
 6     printf("Begin ....\n");//此处缺少“\n”结果会不一样,这是由于printf有缓冲区机制,往屏幕上输出,会有行缓冲
 7     pid_t pid = fork();
 8     printf("End ....\n");
 9     return 0;
10 }

>make

>./fork

(可以知道结束了两个进程。)

》getpid获得当前进程的PID和进程ID,,getppid——获得当前进程父进程的ID

man getpid

pid_t getpid(void);

pid_t getppid(void);

 

8、fork创建子进程

>vi fork.c

 1 #include<stdio.h>
 2 #include<unistd.h>
 3 #include<stdlib.h>
 4 
 5 int main()
 6 {
 7     printf("Begin ....\n");
 8     pid_t pid = fork();
 9     if(pid < 0){
10         perror("fork err");
11         exit(1);
12     }
13     if(pid == 0){
14         //子进程
15         printf("I am a child,pid = %d,ppid = %d\n",getpid(), getppid());
16     }
17     else if(pid > 0){
18         //父进程的逻辑
19         printf("childpid=%d,self=%d,ppid=%d\n",pid,getpid(),getppid());
20         sleep(1);//让父进程等待一段时间,在死去。
21     }
22     
23     printf("End ....\n");
24     return 0;
25 }

>make

>./fork

 

9、进程控制的命令

>vi fork.c

 1 #include<stdio.h>
 2 #include<unistd.h>
 3 #include<stdlib.h>
 4 
 5 int main()
 6 {
 7     printf("Begin ....\n");
 8     pid_t pid = fork();
 9     if(pid < 0){
10         perror("fork err");
11         exit(1);
12     }
13     if(pid == 0){
14         //子进程
15         printf("I am a child,pid = %d,ppid = %d\n",getpid(), getppid());
16         while(1){
17             printf("I am a child\n");
18             sleep(1);
19         }
20     }
21     else if(pid > 0){
22         //父进程的逻辑
23         printf("childpid=%d,self=%d,ppid=%d\n",pid,getpid(),getppid());
24         while(1){
25             sleep(1);
26         }
27     }
28     
29     printf("End ....\n");
30     return 0;
31 }

>make

>./fork

让子进程一直保持运行,打开另一个终端查看PPID和PID分析:

》ps aux——查看进程相关信息的指令

》ps ajx——可以查看更多进程相关的信息,从而追溯进程之间的血缘关系

可以看到PPID、PID,可以看出shell进程是所有进程的父亲,继续追溯,可以看到最终父进程是init

(init进程是所有进程的祖先!)

>kill -9 2890

>ps ajx

杀死了父进程,init成为子进程2891新的父亲。

>kill 2891

杀死子进程

》kill指令——给进程发送一个信号

  kill -l 查看信号相关的信息

  SIGKILL 9号信号

  kill -9 pid——杀死进程

 

10、创建n个子进程

需求:让父进程创建n个子进程

>touch nfork.c

>vi nfork.c

 1 #include<stdio.h>
 2 #include<unistd.h>
 3 #include<stdlib.h>
 4 
 5 int main()
 6 {
 7     int n = 5;
 8     int i = 0;
 9     pid_t pid = 0;
10     for(i = 0; i < 5; i++){//父进程循环结束
11         pid = fork();
12         if(pid == 0){
13             //son
14             printf("I am child, pid=%d,ppid=%d\n",getpid(),getppid());
15             break;//子进程退出循环的接口
16         }
17         else if(pid > 0){
18             //father
19             printf("I am father, pid=%d,ppid=%d\n",getpid(),getppid());
20         }
21     }
22     while(1){
23         sleep(1);
24     }
25     return 0;
26 }

>gcc nfork.c

>./a.out

>ps aux | grep a.out |grep -v grep | wc -l

 

11、循环创建n个子进程控制顺序

》需求:精确控制各个子进程

>touch nfork1.c

>vi nfork1.c

 1 #include<stdio.h>
 2 #include<unistd.h>
 3 #include<stdlib.h>
 4 
 5 int main()
 6 {
 7     int n = 5;
 8     int i = 0;
 9     pid_t pid = 0;
10     for(i = 0; i < 5; i++){//父进程循环结束
11         pid = fork();
12         if(pid == 0){
13             //son
14             printf("I am child, pid=%d,ppid=%d\n",getpid(),getppid());
15             break;//子进程退出循环的接口
16         }
17         else if(pid > 0){
18             //father
19             //printf("I am father, pid=%d,ppid=%d\n",getpid(),getppid());
20         }
21     }
22     
23     sleep(i);
24     if(i < 5){
25         printf("I am child, will exit,pid=%d,ppid=%d\n",getpid(),getppid());
26     }
27     else{
28         //father
29         printf("I am parent, will out,pid=%d,ppid=%d\n",getpid(),getppid());
30     }
31     
32     return 0;
33 }

>gcc nfork1.c

>./a.out

 

12、父子进程共享的内容

 

13、父子进程不共享全局变量

 

 

14、execlp函数介绍

 

 

15、exec函数规律

 

16、exel实现自定义程序

 

 

17、孤儿进程与僵尸进程

》孤儿进程:父亲死了,子进程被init进程领养。

》僵尸进程:子进程死了,父进程没有回收子进程的资源(PCB)。

 

wait函数简单使用和说明

 

 

wait回收并且查看死亡原因

 

 

waitpid回收子进程

 

 

用wait回收多个子进程

 

 

waitpid回收多个子进程

 

 

 

 

在学习Linux系统编程总结了笔记,并分享出来。有问题请及时联系博主:Alliswell_WP,转载请注明出处。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值