Linux系统编程---进程

目录

1.进程的概念

1.1 进程的定义

1.2 在Linux系统中如何查看进程

进程号

案列1

案例2:查看进程中的PID号

2进程的创建 

2.1 进程的创建 fork 函数

C程序的存储空间是如何分配

地址空间:包括进程上下文、进程堆栈、打开的文件描述符、信号控制设定、进程优先级、进程组号等。子进程所独有的只有它的进程号,计时器等。因此,使用fork函数的代价是很大的。

案例3:创建子进程(不区分父子进程 不推荐写)

案例4:区分父子进程

2.2 子进程继承父进程的空间

案例5:父子进程空间问题 

案例6: 子进程继承父进程的空间

案例7: 父子进程的pid返回值(补充)

2.3 创建新进程的目的

案例8:创建多个进程的作用

2.4进程的创建 vfork 函数

案例9:使用vfork创建函数

3.1 进程的退出

3.1正常退出和异常退出

3.2 等待子进程退出 

案例10:僵尸进程,子进程退出时,没有被收集

防止出现僵尸进程

案例11:添加wait后的效果

​编辑

案例12:检测子进程退出的状态

waitpid()函数

​编辑

案例13:使用waitpid()     (用的不多)

结果:父子进程可以交替运行,父进程不用阻塞 

孤儿进程

案例14 验证②

4.exec族函数 

案例15:验证execl返回值 (ps:注意路径的问题,只有在当前的路径才行)

案例16:用excel函数代替ls显示文件列表

​编辑

案例18:execlp() 不用加绝对路径实现ps命令

案例19:使用execvp() 函数

案例20:exec和fork配合使用

5.system函数 

案例21:用system函数代替execl函数

案例21:用system函数代替ps命令,查看进程

6.popen函数

好处:相比于system的好处就是,可以获取程序运行时的输出结果

案例22:获取指令的结果,并且打印出来


1.进程的概念

1.1 进程的定义

程序:程序是存放在存储介质上的一个可执行文件。
进程:进程是程序的执行实例,包括程序计数器、寄存器和变量的当前值。

程序是静态的,进程是动态的

在 linux 系统中进程号(进程标识符)由 0 开始。
进程号为 0 及 1 的进程由内核创建。
进程号为 0 的进程通常是调度进程,常被称为交换进程(swapper)。进程号为 1 的进程通常是 init 进程。
除调度进程外,在 linux 下面所有的进程都由进程 init 进程直接或者间接创建。

1.2 在Linux系统中如何查看进程

ps命令、ps -aux命令

-------------------------------------------------------------------------------------------------------------------------------

查看特定的字段进程-----管道命令(grep)

grep init

------------------------------------------------------------------------------------------------------------------------------- 

查看进程的占用率的情况----top命令

 

------------------------------------------------------------------------------------------------------------------------------- 

进程号

每个进程都由一个进程号来标识,其类型为pid_t,进程号的范围:0~32767
进程号是由操作系统随机给当前进程分配的,不能自己控制进程号总是唯一的,但进程号可以重用。当一个进程终止后,其进程号就可以再次使用了

进程号(PID)

标识一个进程的非负整型数
父进程号(PPID)
任何进程(除 init 进程)都是由另一个进程创建,该进程称为被创建进程的父进程,对应的进程号称为父进
程号(PPID)。
进程组号(PGID)
进程组是一个或多个进程的集合。他们之间相互关联,进程组可以接收同一终端的各种信号,关联的进
程有一个进程组号(PGID) 。
Linux 操作系统提供了三个获得进程号的函数 getpid()、getppid()、getpgid()。
需要包含头文件:

1 #include <sys/types.h>
2 #include <unistd.h>
3 pid_t getpid(void);
4 功能:获取当前进程的进程号
5 pid_t getppid(void);
6 功能:获取当前进程的父进程的进程号
7 pid_t getpgid(pid_t pid);
8 功能:获取当前进程所在进程组的
案列1
#include <stdio.h>
2 #include <sys/types.h>
3 #include <unistd.h>
4
5 int main(int argc, char const *argv[])
6 {
7     //获取当前进程的进程号
8     printf("pid = %d\n", getpid());
9
10     //获取当前进程的父进程的id
11     printf("ppid = %d\n", getppid());
12
13     //获取当前进程所在组的id
14     printf("pgid = %d\n", getpgid(getpid()));
15
16     while(1)
17     {
18
19     }
20
21     return 0;
22 }

运行结果: 

案例2:查看进程中的PID号
#include<stdio.h>
#include<sys/tyoes.h>
#include<unistd.h>

int main()
{
        pid_t pid;
        pid = getpid(); 
        prinf("my pid is = %d\n",pid);  
        
        while(2);  //防止进程终止

        return 0;
}
~                                                                                             
~                                                                                             
~                                                                                             
~                                                                                             
~                               

运行结果:

使用top查看进程占用率

结果:可以看到当前进程由于while一直循环未退出,导致进程占用率百分之百

2进程的创建 

2.1 进程的创建 fork 函数

在 linux 环境下,创建进程的主要方法是调用以下两个函数:

#include <sys/types.h>
#include <unistd.h>
pid_t fork(void);pid_tvfork(void)

创建一个新进程

pid_t fork(void)


功能:
fork()函数用于从一个已存在的进程中创建一个新进程,新进程称为子进程,原进程称为父进程。
返回值:
成功:子进程中返回 0,父进程中返回子进程 ID。
失败:返回-1。

C程序的存储空间是如何分配

地址空间:
包括进程上下文、进程堆栈、打开的文件描述符、信号控制设定、进程优先级、进程组号
等。子进程所独有的只有它的进程号,计时器等。因此,使用fork函数的代价是很大的。

示意图(用fork函数的代价还是比较大的):

案例3:创建子进程(不区分父子进程 不推荐写)
#include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 int main(int argc, char *argv[])
5 {
6     //通过fork函数创建一个子进程
7
8     //注意:主要执行一次fork,就会在原有的进程基础上创建一个新的子进程
9     //而且如果fork之后不区分父子进程的代码区,则后面所有的代码都会执行
10     fork();
11     printf("hello world\n");
12     
13     while(1)
14     ;
15     return 0;
16 }

hello打印两次,也就以为着fork函数创建了一个子进程 

案例4:区分父子进程
#include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 int main(int argc, char *argv[])
5 {
6     //通过fork函数创建一个子进程7
#if 0
9     //注意:主要执行一次fork,就会在原有的进程基础上创建一个新的子进程
10     //而且如果fork之后不区分父子进程的代码区,则后面所有的代码都会执行
11     fork();
12     printf("hello world\n");
13     
14     while(1)
15     ;
16 #endif
17
18     //通过fork函数的返回值来区分父子进程的独立的代码区
19     //父子进程是来回交替执行的,谁先运行,谁后运行是不确定的,不要认为父进程执
行完之后才会执行子进程
20     pid_t pid;
21
22     pid = fork();
23     if(pid < 0)
24     {
25         perror("fail to fork");
26         return ‐1;
27     }
28     else if(pid > 0) //父进程的代码区
29     {
30         while(1)
31         {
32             printf("parent: pid = %d, ppid = %d\n", getpid(), getppid());
33             printf("pid = %d\n", pid);
34             printf("this is a parent process\n");
35             sleep(1);
36             printf("****************\n");
37         }
38     }
39     else //子进程的代码区
40     {
41         while(1)
42         {
43             printf("son: pid = %d, ppid = %d\n", getpid(), getppid());
44             printf("this is a son process\n");
45             sleep(1);
46             printf("‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐\n");

        }
48     }
49
50     return 0;
51 }

说明两个情况:1.上面的等号关系

   

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值