进程的概念
程序:二进制文件
进程:启动的程序
所有的数据都在内存中
需要占据更多的系统资源
cpu,物理内存(RAM)
并行和并发
并发:在操作系统中,是指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是 在同一个处理机上运行
并发不是真正意义上的“同时进行”,只是CPU把一个时间段划分成几个时间片段(时间区间),然后在这几 个时间区间之间来回切换,由于CPU处理的速度非常快,只要时间间隔处理得当,即可让用户感觉是多个应 用程序同时在进行。如:打游戏和听音乐两件事情在同一个时间段内都是在同一台电脑上完成了从开始到结 束的动作。那么,就可以说听音乐和打游戏是并发的。
并行:当系统有一个以上CPU时,当一个CPU执行一个进程时,另一个CPU可以执行另一个进程,两个进程 互不抢占CPU资源,可以同时进行,这种方式我们称之为并行(Parallel)。
其实决定并行的因素不是CPU的数量,而是CPU的核心数量,比如一个CPU多个核也可以并行
并行和并发的区别:
并发,指的是多个事情,在同一时间段内同时发生了。
并行,指的是多个事情,在同一时间点上同时发生了。
并发的多个任务之间是互相抢占资源的。
并行的多个任务之间是不互相抢占资源的。
只有在多CPU或者一个CPU多核的情况中,才会发生并行。否则,看似同时发生的事情,其实都是并发执行的。
PCB(进程控制块)
每个进程在内核中都有一个进程控制块(PCB)来维护进程相关的信息,linux内核的进程控制块是task_struct结构体。
我们简单掌握以下即可:
进程id。系统中每个进程有唯一的id,在C语言中用pit_t类型表示,其实就是一个非负整数
进程的状态,有就绪,运行,挂起,停止等状态。
进程切换时需要保存和恢复一些CPU寄存器 描述虚拟地址空间的信息
描述控制终端的信息
当前工作目录(Cueernt Working Directory)
umask掩码
文件描述符,包含很多指向file结构体的指针
和信号相关的信息 用户id和组id,stat
会话(Session)和进程组
进程可以适用的资源上线(Resource Limit),umilit -a
进程状态
进程基本的状态有五种,分别为初始态,就绪态,运行态,挂起态和终止态。
其中初始态为进程准备阶段,常常与就绪态结合来看。
进程的控制
fork函数
包含的头文件:#include<sys/types.h>
#include<unisted.h>
函数原型:pid_t fork(void);
两个返回值: =0:当前进程为子进程
>0:当前进程为父进程
‐1,出错
fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程,也就是两个进程可以做完全相同的 事,但如果初始参数或者传入的变量不同,两个进程也可以做不同的事。
一个进程调用fork()函数后,系统先给新的进程分配资源,例如存储数据和代码的空间。然后把原来的进 程的所有值都复制到新的新进程中,只有少数值与原来的进程的值不同。相当于克隆了一个自己。
判断父进程和子进程的方法:
进程的ID不一致(但是用户数据相同)
fork函数的返回值
子进程创建成功后,子进程的执行位置
父子进程的执行顺序不同
getpid/getppid函数
getpid:得到当前进程的PID
getppid:得到当前进程的父进程的PID
这里我们可以写一串代码来查看进程之间的顺序
我们会发现当运行时,发现有的输出的值出现在了我们的终端上面,因为运行的时候shell进程也会和其他进程抢占CPU的资源,而且执行多次时,进程的返回的PID不一定一样。虽然上面每次执行的时候都是父进程先执行,但是实际上是不一定的,
关于PID:
PID(进程标识符)是操作系统中用于唯一标识一个进程的数字编号。每个进程在操作系统中运行时,都会被分配一个唯一的PID。这个PID在进程的生命周期内保持不变,直到进程结束或被系统回收。PID的分配通常是连续的,但是当一个进程结束后,它的PID会被系统回收并重新使用。这意味着,在不同的时间点,相同的PID可能分配给不同的进程。在Linux系统中,PID是一个无符号整数,其范围通常是1到32767。
关于fork函数的应用:最常见的就是多进程并发处理任务,可以使用fork函数创建多个子进程来并发处理这些任务。每个子进程独立运行,可以同时执行不同的任务,从而加快任务处理速度。父进程可以通过等待子进程结束并获取子进程的返回结果,来实现多任务的并发处理。其他的还有服务器编程,守护进程的创建,进程池的实现,父子进程间的通信等。
fork函数的基本特点:
- 调用一次,返回两次:fork函数被调用一次,但在父进程和子进程中各返回一次。在父进程中,fork返回新创建的子进程的进程ID;在子进程中,fork返回0;如果调用失败,则返回-1。
- 父子进程独立性:子进程是父进程的副本,但它有自己的进程ID、用户ID、组ID等。子进程对变量的改变不会影响到父进程,因为它们各自拥有独立的地址空间。
- 资源共享与隔离:父子进程共享某些资源(如文件描述符),但它们在内存和堆栈等方面是隔离的。这意味着子进程对内存的修改不会影响到父进程。
ps和kill命令
ps命令用于显示进程信息,kill命令用于终止进程。
ps
ps命令是Linux系统中用于显示当前系统中运行的进程状态的命令。它提供了丰富的选项来显示不同级别的进程信息,如进程ID、父进程ID、CPU和内存使用情况等。
常用选项和用法:
- ps:显示当前终端会话中属于当前用户的进程列表。
- ps -ef:显示系统中所有进程的列表,包括其他用户的进程。该选项提供了进程的全格式信息,包括进程ID、父进程ID、CPU使用率、内存使用率等。
- ps -aux:显示详细的进程信息,包括CPU和内存使用情况等。这个选项非常全面地展示了系统中所有进程的详细信息。
- ps -u [用户名]:显示与指定用户相关的进程信息。可以通过指定用户名来限制显示的进程列表。
- ps -p [PID]:显示指定进程ID的进程信息。可以通过指定PID来查看特定进程的详细信息。
- ps -o [选项]:自定义输出格式。使用该选项可以指定要显示的列和排序方式。例如,
ps -eo pid,ppid,cmd,%mem,%cpu --sort=-%mem
会显示进程ID、父进程ID、命令行、内存使用率和CPU使用率,并按内存使用率降序排序。 - ps -ef | grep [进程名]:查找指定进程名的进程信息。这通常用于过滤出特定进程的详细信息。
这边我总结了几个
a:显示现行终端机下的所有程序,包括其他用户的程序
u:以用户名为主的格式来显示程序状况
x: 显示所有程序,不宜终端机来区分
au
aux
ajx
注意:
- 使用ps命令时,可以根据需要选择合适的选项来获取所需的进程信息。
- ps命令的输出结果包含了多个字段,如PID、PPID、CPU、MEM等,分别表示进程ID、父进程ID、CPU使用率、内存使用率等信息。
kill
kill命令是Linux系统中用于终止指定进程运行的命令。它通过向进程发送特定信号来结束相应的进程。默认情况下,kill命令发送的是SIGTERM(信号编号为15)信号,要求进程正常退出。如果进程无法响应SIGTERM信号,可以使用SIGKILL(信号编号为9)信号来强制终止进程。
常用选项和用法:
- kill [PID]:终止指定进程ID的进程。这是最基本的用法。
- kill -9 [PID]:强制终止指定进程ID的进程。使用SIGKILL信号,该信号无法被进程捕获或忽略,因此可以无条件终止进程。
- kill -l:列出所有可用的信号。这可以帮助用户了解kill命令支持的所有信号及其编号。
- kill -s [信号编号] [PID]:向指定进程发送特定信号。用户可以根据需要发送不同的信号来影响进程的行为。
- killall [进程名]:终止所有指定进程名的进程。这适用于需要终止多个同名进程的情况。
- pkill [进程名]:与killall类似,也是用于终止所有指定进程名的进程,但pkill提供了更多的匹配模式选项。
注意:
- 在使用kill命令时,需要谨慎操作,避免误终止重要进程导致系统异常。
- 强制终止进程(如使用kill -9)可能会导致数据丢失或系统不稳定,因此应尽量避免使用。
- 如果用户没有足够的权限来终止某个进程,可以使用sudo命令来提升权限执行kill命令。
这里我们举一个例子
使用一个死循环,使其每一秒打印一次hello world!
我们想要停止该程序
利用ps指令寻找,并执行kill -9命令
文件被成功终止