1.进程基本概念
1、什么是程序?什么是进程?有什么区别?
程序是静态的概念,gcc xxx.c –o pro,磁盘中生成pro文件,叫做程序
进程是程序的一次运行活动,通俗点意思是程序跑起来了,系统中就多了一个进程
2、如何查看系统中有哪些进程?
a.使用ps指令查看,实际工作中,配合grep来查找程序中是否存在某一个进程
ps -aux|grep init
b.使用top指令查看,类似windows任务管理器工作中,配合grep来查找程序中是否存在某一个进程
3、什么是进程标识符?
每个进程都有一个非负整数。表示的唯一ID,叫做pid,类似身份证。
pid:进程标识符:非负整数
pid=0:交换进程,作用:进程调度;
pid=1:init进程,作用:系统初始化
编程调用getpid()函数获取自身的进程标识符
getppid()获取父进程的进程标识符。
#include <sys/types.h>
#include <unistd.h>
pid_t getpid(void);
pid_t getppid(void);
4、父进程和子进程
进程A创建了进程B
那么A叫做父进程,B叫做子进程,父子进程是相对的概念,理解为人类中的父子关系。
5、C程序的存储空间是如何分配的?
简单来说:
高地址: 命令行参数和环境变量
栈:函数调用,局部变量,函数调用产生的信息都放在栈里面
堆:malloc在堆里申请空间
Bss段:函数外未初始化的数据
数据段:初始化的数据
代码段:正文段
2.创建进程
fork():
#include <sys/types.h>
#include <unistd.h>
pid_t fork(void);
返回0,代表子进程;
返回子进程pid,代表父进程
失败,返回-1;
写实拷贝:代码段共享,数据段发生改变时再拷贝。
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
pid_t pid;
int data = 10;
printf("father: id=%d\n",getpid());
pid = fork();
if(pid > 0)
{
printf("this is father print, pid = %d\n",getpid());
}
else if(pid == 0){
printf("this is child print,child pid = %d\n",getpid());
data = data+100;
}
printf("data=%d\n",data);
return 0;
}
创建子进程的目的:
vfork():
#include <unistd.h>
pid_t vfork(void);
返回0,代表子进程
返回子进程pid,代表父进程
跟fork()的区别:
- vfork直接使用父进程存储空间,不拷贝
- vfork保证子进程先运行,当子进程调用exit退出后,父进程才开始执行。
3.进程退出
正常退出:
异常退出:
![](https://i-blog.csdnimg.cn/blog_migrate/8154cb398f93a331aa2391ea7421e92d.png)
4.等待子进程退出
父进程等待子进程退出,并收集子进程的退出状态
子进程退出状态不被收集,变成僵死进程(僵尸进程)
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *wstatus);
pid_t waitpid(pid_t pid, int *wstatus, int options);
wait:使调用者阻塞,waitpid:有一个选项,可以使调用者不阻塞。
status参数:是一个整型数指针
非空:子进程退出状态放在它所指向的地址中。
空:不关心退出状态
孤儿进程:父进程如果不等待子进程退出,在子进程之前就结束了自己的“生命”,此时子进程叫做孤儿进程。
Linux避免系统存在过多孤儿进程,init进程收留孤儿进程,变成孤儿进程的父进程