进程---Linux/C语言

为什么要学习进程?

我们现在的很多程序,在执行的过程中,需要同时处理多个任务,因此我们需要学习多进程或多线程来实现多任务处理的需要,可以提高我们程序的执行效率

进程的概念

一个正在运行的程序以及它所依赖的资源的总称,进程也是系统进行资源分配的基本单位,也是线程的容器

进程与线程

进程是程序的执行过程,程序是进程的执行文本,一个进程只能对应一个程序,一个程序可以对应多个进程

查看进程

Windows:任务管理器

Linux:top(动态查看有哪些进程),ps

杀死进程:kill + pid

进程标识符pid

在某个时刻,计算机中运行了多个程序,这些程序对于内核来说,如何进行调度,如何进行管理,因此,系统给每个正在运行的程序都分配了一个大于等于0的正整数的编号,这个编号就是我们的进程标识符

在计算机中,系统一旦被运行,默认就会创建三个特殊的进程 0,1,2

进程pid的编号一般是0-32767

程序是如何转换成进程?

程序需要从硬件加载到内存,在加载的同时系统会为该程序在内存中划分内存四区

内核会为该程序构建一个内存块(结构体),来描述该进程的相关信息(内核需要登记运行程序的相关信息),将该进程加入就绪队列

进程控制块PCB

为了更好的对每个进程做描述它的本质是一个结构图 size>=1KB

进程的状态

就绪,停止,阻塞

就绪:

进程已经获取到除处理器外的所有资源,等待分配处理器资源,只要分配到处理器资源就可以运⾏。⼀般就绪进程是会有⼀个就绪进程队列,有系统来调度。

运⾏:

进程正在执⾏。

进程阻塞:

进程因等待某个事件发⽣⽽暂停运⾏。

停⽌ (stop) :

进程已经完成任务。

进程的状态转化:

运⾏----> 就绪 正在运⾏的进程因时间⽚到,转⼊就绪队列等待重新调度。

就绪--->运⾏ 系统进⾏进程调度,拿出就绪队列中的某个进程运⾏。

运⾏----> 等待 正在运⾏的进程因等待某事件发⽣,转⼊等待状态。

等待--->就绪 处于等待状态的进程,因所等待的事件发⽣了,进⼊就绪对队列让系统调度运⾏。

进程的特点

(1)动态性:进程的实质是程序的⼀次执⾏过程,进程是动态产⽣,动态消亡的。

(2)并发性:任何进程都可以同其他进程⼀起并发执⾏。

(3)独⽴性:进程是⼀个能独⽴运⾏的基本单位,同时也是系统分配资源的独⽴单位;

(4)异步性:由于进程间的相互制约,使进程具有执⾏的间断性,即进程按各⾃独⽴的、不可预知的速度向前推进。

进程的分类

在Linux操作系统中,进程⼤致可以分为3中不同的类型,每种进程都有⾃⼰的特点和属性。

交互进程:也称为终端进程,由⼀个Shell启动的进程,交互进程既可以在前台运⾏,也可以在后台运⾏。

批处理进程:这种进程和终端没有联系,即执⾏的是批处理⽂件、shell脚本。

监控进程:也称守护进程(daemon)是⼀类在后台运⾏的特殊进程,⽤于执⾏特定的系统任务。守护进程⼀般在系统启动时开始运⾏,除⾮强⾏终⽌,否则直到系统关机都保持运⾏。

进程的创建

创建进程有两种⽅式:1)操作系统创建 2)⽗进程创建。

进程的创建可以通过system函数、exec系列函数(execl、execlp等)、fork函数实现。

system函数

函数原型为: int system(const char*filename)

使⽤时需要包含头⽂件: stdlib.h

主要⽤于执⾏shell命令。

功能为:建⽴独⽴进程,拥有独⽴的代码空间,内存空间,等待新的进程执⾏完毕,system才返回.(阻塞),system函数其实内部会调⽤fork函数来产⽣⼦进程。

复制进程fork函数

函数原型为: pid_t fork(void)

功能:fork 函数会新⽣成⼀个进程,调⽤ fork 函数的进程为⽗进程,新⽣成的进程为⼦进程。⼦进程复制了⽗进程打开的⽂件描述符。

函数返回值:函数返回类型 pid_t 实质是 int 类型,Linux 内核 2.4.0 版本的定义是:

在⽗进程中返回⼦进程的 pid,在⼦进程中返回 0,失败返回-1。

所属头⽂件:unistd.h

上述代码总结:

fork函数被⽗进程调⽤⼀次,但是却返回两次;⼀次是返回到⽗进程(⼦进程id),⼀次是返回到新创建的⼦进程(是0)。

被fork的⼦进程会和和它⽗进程⼀样,继续执⾏当前的程序。

fork()函数出错可能有两种原因:

1、当前的进程数已经达到了系统规定的上限,这时errno的值被设置为EAGAIN

2、系统内存不⾜,这时errno的值被设置为ENOMEM

练习

利用多进程,设计一个程序实现交替打印ping和pong字符串

复制代码
 #include <stdio.h>
 #include <unistd.h>
 #include <sys/types.h> 
 ​
 int main()
 {
     int i = 0;
     for(;i<3;i++)
     {
     fork();
     printf("pin  \n");
     printf("pong  \n");
 }
 ​
 } 

设计程序创建三个子进程实现一个打印"###",一个打印"$$$",另外一个打印"***"

复制代码
 #include <stdio.h>
 #include <unistd.h>
 #include <sys/types.h> 
 ​
 int main()
 {
     pid_t a,b,c;
     a = fork();
     printf("###\n");
     if (a <= 0)
     exit (0);
     
     b = fork();
     printf("$$$\n");
     if (b <= 0)
     exit (0);
     
     c = fork();
     printf("***\n");
     if (c <= 0)
     exit (0);
 ​
 } 

设计一个程序,检测一个数组中的数据是否全是连续的,比如{7,8,9,10}就是连续的,{3,5,8,9}就不是

复制代码
 #include <stdio.h>
 #include <unistd.h>
 #include <sys/types.h> 
 #include <stdlib.h>
 ​
 void fun(int **a,int n)
 {   int i = 0;
     int b = 0;
     for(;i<n - 1;i++)
     {
         if(*a[i]+1 == *a[i+1])
         b++;
     }
     if(b == 3)
     printf("他是连续的数据\n");
     else
     printf("不是连续的数据\n");
 }
 ​
 int main()
 {
     int a = 7,b = 8,c = 9, d = 10,a1 = 3,b1 = 5,c1 = 8,d1 = 9;
     int *arr1[] = {&a,&b,&c,&d};
     int *arr2[] = {&a1,&b1,&c1,&d1};
     fun(arr1,4);
     fun(arr2,4);
     return 0;
 } 
相关推荐
木井巳8 小时前
【递归算法】验证二叉搜索树
java·算法·leetcode·深度优先·剪枝
不当菜虚困8 小时前
windows下HSDB导出class文件报错【java.io.IOException : 系统找不到指定的路径。】
java·开发语言
lsx2024068 小时前
Vue.js 循环语句
开发语言
m0_561359678 小时前
嵌入式C++加密库
开发语言·c++·算法
近津薪荼8 小时前
优选算法——双指针专题7(单调性)
c++·学习·算法
小马爱打代码8 小时前
Spring Boot:第三方 API 调用的企业级容错设计
java·spring boot·后端
j445566118 小时前
C++中的职责链模式实战
开发语言·c++·算法
m0_686041618 小时前
实时数据流处理
开发语言·c++·算法
梵刹古音8 小时前
【C语言】 字符型变量
c语言·开发语言·嵌入式
草履虫建模8 小时前
A13 String 详解:不可变、常量池、equals 与 ==、性能与常见坑
java·开发语言·spring·jdk·intellij-idea·java基础·新手