Linux 进程——学习笔记 简单粗暴直击要害

目录

一、程序是什么?

二、进程是什么?

三、程序的启动过程

1、启动例程是什么

2、启动例程作用

3、图示:程序的启动到退出

四、进程的创建

子进程的继承问题

五、进程的八种终止方式

六、进程常见的五种状态

七、根据进程功能使命的不同,可分为3类进程


一、程序是什么?

程序是存放在磁盘文件中的可执行文件。应用程序就是程序员写的代码,在应用程序没有运行时,这些代码就是一堆存储在硬盘里的机器指令


二、进程是什么?

是程序的执行实例,运行中的程序,每个进程运行在其各自的虚拟地址空间,实现了互不干扰。不同进程间可通过内核控制机制进行相互通讯,如 IPC。

当一个程序开始执行时,它会经历以下步骤逐渐转变为一个进程:

  • 加载:可执行程序被加载到内存中。在加载过程中,操作系统将可执行文件中的代码和数据载入物理内存的合适位置。
  • 创建进程控制块 (PCB):操作系统为该进程创建一个进程控制块 (PCB),也称为进程描述符。PCB是存储进程相关信息的数据结构,包括进程的标识符、状态信息、资源分配情况等。


三、程序的启动过程

1、启动例程是什么

程序要执行时,总得从某个地方开始执行,在进程的 main 函数(作为当前进程的入口,也是当前进程的出口)执行之前,内核会先启动一个特殊的例程,这个特殊的例程也是一个进程,称为启动例程。启动例程是一开始就编译好的,属于操作系统的一部分,编译器在编译用户程序时将启动例程编译进可执行文件中。

2、启动例程作用

1)搜集命令行(即终端输入的命令,如./test hello 123)的参数传递给main函数中的argc和argv;

2)搜集环境信息(如shell,path)构建环境表(是main函数的第三个参数)并传递给main函数;

3)登记进程的终止函数(启动例程默认登记的是 exit;常见的有 return、exit、_exit;),作为进程结束时默认调用的终止函数;

(进程块结束时会自动调用终止函数。也可通过 atexit 函数向内核登记自己定义的退出函数,让进程终止前调用它)

3、图示:程序的启动到退出

执行程序时,内核会调用 exec 函数,从 C 启动例程开始执行,启动例程从内核中取得命令行参数和环境变量,然后调用 main 函数。注意,内核想要执行程序的唯一方法是调用 exec 函数。进程自动终止的唯一方法是调用 exit、_exit、_Exit,如上图所示。在进程结束时,可以调用 atexit 来向内核登记一些函数,这些函数被称为终止函数,exit 会自动调用


四、进程的创建

新进程的创建,都是由一个存在的进程执行创建进程的 API 函数而被创建的。

头文件

#include<sys/types.h>

#include<unistd.h>

函数

pid_t  fork (void);

功能:创建子进程,父子进程哪个先运行根据系统调度来决定;

pid_t  vfork (void);

功能:创建子进程,子进程先运行,父进程阻塞;

返回值

成功:给子进程返回 0,给父进程返回 子进程ID;

失败:返回 -1;

 注意事项:子进程被创建后,父进程中已经运行过的代码,在子进程中不再运行了,示例如下:

父进程调用 fork 创建子进程,调用 fork 前的程序父进程已经自己执行过了,子进程不再重复运行。所以子进程不会再执行一次第一个printf,所以只输出了一个“调用fork前...”。

子进程的继承问题

进程的创建,其实就是以父进程为模板,复制出一个新进程作为子进程,数据段、堆、栈内容跟父进程一模一样,代码段也跟父进程一样,子进程相当于父进程的副本(原本父进程中变量所对应的虚拟地址是什么,也被子进程一并复制过去了)。虽说父子进程长的类似,但已是两个不相干的进程,是各自执行,两者在不同的内存地址中,从调用 fork 函数那一刻起,内存就出现父进程和子进程两个进程表项,两块内存区域。(继承的图示如下)

子进程能从父进程继承的信息

从父进程那里拷贝:用户信息和权限、目录信息、信号信息、环境、资源限制、堆、栈、数据段;

跟父进程一起共享:代码段(也称正文段)、存储段;

子进程不能从父进程继承到的信息

(子进程自己创建独有的)

进程ID、锁信息、运行时间、未决信号

父进程的程序如果需要操作文件,如调用了文件 IO,则 fork 出的子进程也要操作文件(因为父子进程的代码段相同),创建出的子进程内核空间对比父进程的有什么变化:(操作文件的进程在内核中有3个数据结构:进程表项、文件表项、i节点

从内核看,父进程哪些信息被子进程继承

继承:

拷贝父进程的 文件描述表(进程表项的一部分)给自己使用;

共享父进程的 文件表项、i节点;

不继承:

除文件描述表外的进程表项内容,子进程自己创建,唯一独有;


五、进程的八种终止方式

正常终止(5种)

1 从main函数返回,return 0(标准C库函数)

2 调用 exit(标准C库函数)

3 调用_exit 或_Exit(系统调用)

4 最后一个线程从其启动例程返回;

5 最后一个线程调用 pthread_exit(系统调用)

异常终止(3种)

1 调用 abort(系统调用)

2 接收到一个信号并终止(如异常操作,代码报错等)

3 最后一个线程对取消请求做处理响应

3种常见退出方式的比较: 

return

exit()

_exit()或_Exit()

是否刷新标准 I/O 缓存

是否自动调用终止函数


六、进程常见的五种状态

创建状态一个应用程序从 OS 上启动,首先会进入创建状态,向系统申请系统资源创建进程管理块(PCB:Process Control Block),往里面填入必要的信息,完成资源的分配。
就绪状态进程成功创建后,会进入就绪状态,等待获取 CPU 的使用权

运行状态

获取了 CPU 使用权的进程,是正在运行中的的进程

阻塞状态

在运行状态期间,如果进行了阻塞的操作,如耗时的I/O操作,此时进程暂时无法操作就进入到了阻塞状态,在这些操作完成后就进入就绪状态

终止状态进程结束或者被系统终止,进入终止状态

进程的状态转换图:


七、根据进程功能使命的不同,可分为3类进程

守护进程

一直在后台运行的进程(即始终在内存中运行),是生存期很长的一种进程,常常在系统引导装入时启动,在系统关闭时终止;

守护进程都必须以超级用户(用户ID为0)的优先权来运行;

守护进程没有控制终端,没有前台,没有在屏幕前台显示;

守护进程的父进程都是init进程;

孤儿进程

父进程结束后,子进程就会变成孤儿进程,会由1号进程init进程领养;一个子进程的父进程退出后,init进程就会成为该子进程的父进程,当该子进程退出时, init进程会调用wait来释放该子进程在进程表中占用的资源

僵尸进程

子进程结束但没有完全释放内存,即子进程的进程表项task_struct没有释放,子进程变成僵尸进程

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值