03.进程

并发

进程是运行起来的程序,是OS(操作系统)进行资源分配和调度的基本单位。
当只有一个cpu,进程遇到阻塞事件的时候(可能是要去磁盘中读取数据),我们知道cpu的执行速度和磁盘的IO速度相差特别大,cpu不可能一直等待这个进程去读数据,该遇到阻塞事件的进程会被挂起,cpu会执行下一个进程。
所以cpu会在各个进程之间进行快速的切换,而每个进程的执行也只有那么一瞬间,这也就造成cpu好像在同时执行多个程序的错觉

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

进程状态

一个进程开始执行,会遇到以下几种状态

运行态

进程正在占用cpu时间片运行时候

就绪态

该进程准备好了可以运行,但是cpu正被其他进程占用

阻塞态(挂起态)

该进程遇到了阻塞事件,进程会挂起,需要等待阻塞事件结束后才能继续运行,此时及时给cpu的使用权,该进程也无法运行

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

状态的切换

运行态到阻塞态:当进程遇到阻塞事件的时候
阻塞态到就绪态:当阻塞事件结束时
就绪态到运行态:操作系统的进程调度程序选中后,分配cpu的使用权,开始运行
运行态到就绪态:进程运行过程中,分配的时间片用完了,操作系统会将其变成就绪态,接着从就绪态的进程中选择一个运行

处于就绪态的程序有很多,操作系统该如何去选择,处于运行态的进程也有很多,他们该运行多久,这需要程序调度算法来分配,一般位时间片轮转算法

PCB

进程控制块

每一个进程在内核中都有一个进程控制块,PCB是一个结构体,里面有很多成员变量

1.pid进程id

2.进程的状态(运行态、阻塞态、就绪态)

3.进程的虚拟地址
4.文件描述符表
5.进程切换时需要保存和回复的一些变量,cpu寄存器
6.描述控制终端的信息
7.当前工作目录
8.umask掩码
9.uid、gid
零号进程会产生一号进程和二号进程,其他进程都是一号和二号的子进程

子进程

进程产生的俩种方式

运行一段程序,会产生进程

在程序中调用系统调用函数fork,能产生子进程

为什么要这么做?

如果进程遇到了阻塞事件,但是现在不想等阻塞事件结束,就可以调用fork函数,产生子进程,越过阻塞事件,执行下面的程序

fork函数

创建出子进程,子进程和原来的进程的代码是一样的
不光是代码复制过来了,数据段和堆栈都复制了一份

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

从第10行fork开始分叉
fork()返回值为0–>子进程
返回值>0–>父进程
就比如把你复制了一份,这个克隆人具有和你一样的记忆,但是你和克隆人之前对这个世界的影响在只能是你的影响,不会是双份的

父子进程共享同一个文件描述符

#include<stdio.h>
#include<string.h>                                                              
#include<unistd.h>
#include<pthread.h>
#include<fcntl.h>int main(int argc, char* argv[])
{int fd=open("a.txt",O_RDWR);int pid=fork();if(pid == 0){//子进程int write_count=write(fd,"hello\n",6);if(write_count == -1){perror("write:");return -1;}printf("fd = %d\n",fd);printf("write_count = %d\n",write_count);}if(pid > 0){//父进程sleep(1);char buf[1024];int read_count=read(fd,buf,sizeof(buf));if(read_count == -1){perror("read:");return -1;}printf("fd = %d\n",fd);printf("read_count = %d\n",read_count);}while(1);return 0;
}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

#include<stdio.h>
#include<string.h>                                                              
#include<unistd.h>
#include<pthread.h>
#include<fcntl.h>int main(int argc, char* argv[])
{printf("hello");int fd=open("a.txt",O_RDWR);int pid=fork();if(pid == 0){//子进程int write_count=write(fd,"hello\n",6);if(write_count == -1){perror("write:");return -1;}printf("fd = %d\n",fd);printf("write_count = %d\n",write_count);}if(pid > 0){//父进程sleep(1);char buf[1024];int read_count=read(fd,buf,sizeof(buf));if(read_count == -1){perror("read:");return -1;}printf("fd = %d\n",fd);printf("read_count = %d\n",read_count);}while(1);return 0;
}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

缓冲区机制

C语言中,printf输出的内容首先到放到缓冲区中,等到缓冲区刷新后,才会输出到屏幕上

在 C 语言中,printf() 函数不会自动刷新缓冲区。这意味着,如果你在 printf() 语句中不添加换行符 \n,输出内容可能不会立即显示在屏幕上。

原因如下:

  1. 缓冲区机制:

    • 为了提高输出效率,C 语言中的标准输出(通常是屏幕)使用了缓冲区机制。
    • 当你使用 printf() 输出内容时,这些内容首先被写入到内存中的缓冲区,而不是直接输出到屏幕上。
  2. 缓冲区刷新:

    • 缓冲区会在以下情况下自动刷新(即将缓冲区中的内容输出到屏幕):
      • 遇到换行符 \n
      • 缓冲区满了
      • 程序正常退出
    • 如果 printf() 语句中不包含换行符 \n,缓冲区可能不会立即刷新,导致输出结果不会立即显示在屏幕上。

因此,在 printf() 中不加 \n 的情况下,输出内容可能会在缓冲区中暂时保存,直到缓冲区满或程序结束时才会被刷新到屏幕上。如果需要立即看到输出结果,建议在 printf() 语句中添加换行符 \n 或使用 fflush(stdout) 函数来手动刷新缓冲区。

多进程的创建

让子进程不再创建子进程
#include<stdio.h>
#include<string.h>                                                              
#include<unistd.h>
#include<pthread.h>
#include<fcntl.h>int main(int argc, char* argv[])
{int pid;for(int i=1;i<=14;i++){pid = fork();if(pid == 0) break;}printf("process\n");return 0;
}
#include<stdio.h>
#include<string.h>                                                              
#include<unistd.h>
#include<pthread.h>
#include<fcntl.h>int main(int argc, char* argv[])
{2 (0,1)2  03  1  (0,1)4  1   1if(fork()&&fork()){fork();}printf("123\n");2	(0,1)3   14   0   (0,1)5   0    1if(fork()||fork()){fork();}printf("123\n");return 0;
}

查看进程

ps ajx | grep ./main(进程名);

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

结束进程的函数

系统调用函数 -exit()

库函数 exit()

#include<stdio.h>
#include<string.h>                                                              
#include<unistd.h>
#include<pthread.h>
#include<fcntl.h>
#include<stdlib.h>
int main(int argc, char* argv[])
{printf("hello world\n");exit(0);printf("abcd\n");return 0;
}

孤儿进程

父进程先结束,子进程会变成孤儿进程,但是孤儿进程只会存在那么一瞬间,因为会有一个专门回收的init进程去领养孤儿进程
孤儿说明儿子还存在,但是爸爸死了
#include<stdio.h>
#include<string.h>                                                              
#include<unistd.h>
#include<pthread.h>
#include<fcntl.h>
#include<stdlib.h>
int main(int argc, char* argv[])
{int pid=fork();if(pid == 0){while(1){//孤儿进程,被init进程领养,因为每个进程必须有父进sleep(1);printf("child pid = %d,father pid = %d\n",getpid(),getppid());}}if(pid > 0){sleep(10);printf("pid = %d,ppid = %d\n",getpid(),getppid());}return 0;
}

僵尸进程

字面意思,儿子死了,但是没死透,因为它的父亲没了,没人给它收尸
一个人离开世界应该是肉体和精神都消失在这个世界里面,僵尸进程就说明精神死了,但是它的肉体仍然存在这个世界里面。
专业词汇:
子进程先结束,但是父进程尚未回收,子进程残留的资源PCB存放在内核中,变成了僵尸(Zombie)进程
#include<stdio.h>
#include<string.h>                                                              
#include<unistd.h>
#include<pthread.h>
#include<fcntl.h>
#include<stdlib.h>
int main(int argc, char* argv[])
{int pid=fork();if(pid == 0){//僵尸进程printf("child pid = %d,father pid = %d\n",getpid(),getppid());return 0;}while(1);return 0;
}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

进程回收

一个进程在结束的时候会关闭所有文件描述符,释放在用户空间分配的内存,但是它的PCB还保留着,内核在其中保存了一些信息,如果是正常退出则保留退出状态,如果是异常退出则保存着异常终止的信号。
子进程的父进程可以调用wait或者waitpid获取这些信息,然后彻底的除掉这个进程。

wait函数

作用

1.阻塞等待子进程的结束
2.在父进程中回收任意一个子进程的残留资源
3.获取子进程的结束状态

头文件

#include <sys/types.h>

#include <sys/wait.h>

函数形式

int wpid=wait(status);
status是传出参数,是进程的状态
#include<stdio.h>
#include<string.h>                                                              
#include<unistd.h>
#include<pthread.h>
#include<fcntl.h>
#include<stdlib.h>
int main(int argc, char* argv[])
{int pid;for(int i=0;i<5;i++){pid = fork();if(pid == 0){break;}}if(pid>0){int wpid=wait(NULL);printf("hello wpid = %d\n",wpid);while(1);}else{sleep(20);return 0;}while(1);return 0;
}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

#include<stdio.h>
#include<string.h>                                                              
#include<unistd.h>
#include<pthread.h>
#include<fcntl.h>
#include<sys/wait.h>
int main(int argc, char* argv[])
{int pid;for(int i=0;i<4;i++){pid = fork();if(pid == 0) break;}if(pid > 0){int status;int wpid = wait(&status);printf("wpid = %d\n",wpid);//当前回收的进程是id是多少// if(WIFEXITED(status)){//如果程序正常退出// 	printf("child ps return status = %d\n",status);// }if(WIFSIGNALED(status)){//如果程序异常退出printf("kill child ps signal = %d\n",WTERMSIG(status));}while(1);}else{sleep(5);while(1);}return 0;
}

waitpid函数

指定进程id去回收
int wpid=waitpid(wpid,&status,option)
#include<stdio.h>
#include<string.h>                                                              
#include<unistd.h>
#include<pthread.h>
#include<fcntl.h>
#include<sys/wait.h>
int main(int argc, char* argv[])
{int pid;int wpid;for(int i=0;i<4;i++){pid = fork();if(pid == 0) break;if(i == 2){wpid=pid;printf("wpid = %d\n",wpid);}}if(pid > 0){int ret=waitpid(wpid,NULL,0);printf("wpid = %d\n",ret);while(1);}else{sleep(5);return 5;}return 0;
}

若参三为WNOHANG,如果要回收的程序还在运行,则直接返回0,不会杀死该进程(不会阻塞)

参一pid

pid>0,回收指定pid的子进程
pid==0,回收和当前调用进程(父进程)一个组的子进程
pid==-1,回收任意子进程,相当于wait
pid<-1,回收abs(pid)这个组的一个子进程

exec函数族

fork函数创建的子进程后执行的是和父进程相同的程序,如果想在一个程序执行过程中执行另一个程序的话,就需要调用exec函数,通过该调用,被调用的进程会替代当前运行的程序,将当前进程的代码段和数据段全部替换成被调用程序的代码段数据段,但是进程的id不变,进程的名字替换成了被调用程序的名字,肉体还在,精神是别的人的

int execl(path,参1,参2 ,参3 ,NULL);

path–>被调用程序的路径

main.c

在main中调用execl函数,执行a程序,用a程序覆盖main程序,但是进程的id没有改变,进程的名字变成了a程序的
#include<stdio.h>
#include<string.h>                                                              
#include<unistd.h>
#include<pthread.h>
#include<fcntl.h>
#include<sys/wait.h>
int main(int argc, char* argv[])
{printf("cur pid = %d\n",getpid());execl("./a","./a","aa.txt","bb.txt",NULL);//执行其他程序printf("不会执行了\n");return 0;
}

a.c

#include<stdio.h>
#include<string.h>                                                              
#include<unistd.h>
#include<pthread.h>
#include<fcntl.h>
int main(int argc, char* argv[])
{printf("cur pid = %d\n",getpid());printf("argc = %d\n",argc);printf("agrv[0] = %s\n",argv[0]);printf("agrv[1] = %s\n",argv[1]);printf("agrv[2] = %s\n",argv[2]);printf("agrv[3] = %s\n",argv[3]);return 0;
}

int execlp(const char * file,参1,参2,参3,NULL)

file一般为shell命令或者是环境变量
#include<string.h>                                                              
#include<unistd.h>
#include<pthread.h>
#include<fcntl.h>
#include<sys/wait.h>
int main(int argc, char* argv[])
{execlp("ls","ls","/",NULL);return 0;
}
ls的底层是把目录里面的内容输出到终端中,现在把文件描述符值为1的指向该为一个文件,就可以实现输出重定向的内容(ls / >>a.txt)
#include<stdio.h>
#include<string.h>                                                              
#include<unistd.h>
#include<pthread.h>
#include<fcntl.h>
#include<sys/wait.h>
int main(int argc, char* argv[])
{int fd=open("b.txt",O_RDWR | O_CREAT,0644);if(dup2(fd,1)==-1){perror("dup2:");return -1;}execlp("ls","ls",NULL);return 0;
}

覆盖重定向和追加重定向

一个shell命令默认输出到终端上

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/3029342.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

传感器—超声波雷达

声波技术 在讲述超声波雷达之前&#xff0c;先了解一下声波的概念以及超声波和声波之间的关系 什么是声波&#xff1f; 声波是物体机械振动状态&#xff08;或能量&#xff09;的传播形式。所谓振动是指物质的质点在其平衡位置附近进行的往返运动形式&#xff0c;这种振动状…

2023盘古石晋级赛 移动终端取证 WP

9. 根据容恨寒的安卓手机分析&#xff0c;MAC的开机密码是[答案&#xff1a;asdcz] 到这里火眼就寄了&#xff0c;盘古石 启动&#xff01; 10. 根据容恨寒的安卓手机分析&#xff0c;苹果手机的备份密码前4位是[答案&#xff1a;1234] 11. 根据魏文茵苹果手机分析&#xff0c…

找不到vcruntime140_1.dll怎么办,介绍5种简单有效的解决方法

当您的电脑系统提示找不到vcruntime140_1.dll文件时&#xff0c;这通常意味着系统在尝试运行某个应用程序或游戏时&#xff0c;无法定位到这个至关重要的动态链接库&#xff08;DLL&#xff09;文件。此情况可能源于几个不同的原因&#xff0c;包括但不限于&#xff1a;文件被误…

电信网关配置管理系统 rewrite.php 文件上传致RCE漏洞复现

0x01 产品简介 中国电信集团有限公司(英文名称“China Telecom”、简称“中国电信”)成立于2000年9月,是中国特大型国有通信企业、上海世博会全球合作伙伴。电信网关配置管理系统是一个用于管理和配置电信网络中网关设备的软件系统。它可以帮助网络管理员实现对网关设备的远…

三分钟上手安全渗透系统Kali Linux

kali linux系统集成了常用的安全渗透工具&#xff0c;省去了安装工具的时间&#xff0c;做安全相关的工作是非常推荐使用的。 安装Kalii Linux 安装系统 一般使用虚拟机进行安装&#xff0c;Kali Linux基于Debian内核&#xff0c;虚拟机的操作系统选择Debian 7.x 64 选择系统…

C++入门 string类(第二章):string类对象的容量操作

文章目录 &#x1f680;1. string类对象的容量操作⚡️1.1 size⚡️1.2 capacity⚡️1.3 max_size⚡️1.4 resize⚡️1.5 reserve⚡️1.6 clear⚡️1.7 empty &#x1f680;2. string类对象访问元素⚡️2.1 at⚡️2.2 back 与 front &#x1f680;3. string类对象的字符串操作&…

嵌入式学习<1>:建立工程、GPIO和keil仿真

嵌入式学习_part1 本部分笔记用于学习记录&#xff0c;笔记源头 >>b站江科大_STM32入门教程_新建工程 建立工程、GPIO 开发环境&#xff1a;keil MDK、STM32F103C8T6 1 &#xff09;建立工程 &#xff08;1&#xff09;基于寄存器开发、基于标准库 或者 基于HAL库开…

海睿思受邀参加 “走进中节能”研习交流,探索新能源数据治理的创新路径

近日&#xff0c;OceanMind海睿思参加由江苏省企业信息化协会&#xff08;以下简称“苏信会”&#xff09;主办的“走进中节能太阳能科技&#xff08;镇江&#xff09;有限公司”研习交流活动。 海睿思与苏美达、远东控股、隆基乐叶、固德威、上能电气等40多位来自制造业领域的…

VMware Workstation 17 Player 创建虚拟机教程

本教程是以windows server 2012物理机服务器安装好的VMware Workstation 17 Player为例进行演示&#xff0c;安装VMware Workstation 17 Player大家可以自行网上搜索安装。 1、新建虚拟机 双击安装好的VMvare图标&#xff0c;点击创建虚拟机。 2、选择是否安装系统 本步骤选…

socks5代理的工作原理是什么?

SOCKS5代理是一种采用SOCKS协议的代理服务器&#xff0c;是一种通用的代理服务器。SOCKS5代理服务器可以在前端机器和服务器机器之间扮演一个中介角色&#xff0c;使得内部网中的前端机器能够访问Internet网中的服务器&#xff0c;同时提供更加安全的通讯方式。那么&#xff0c…

解决参考文献自动生成标号,换行时自动缩进

问题如下图所示&#xff0c;红色方框部分应该填充内容&#xff0c;但自动生成标号时不会填充&#xff1a; 解决方案&#xff1a; 1. 选中内容&#xff1a; 2. 找到布局-段落&#xff1a; 3. 选择“无”&#xff0c;即可。

苹果电脑免费第三方软件CleanMyMac X2025电脑版垃圾清理软件神器

Mac电脑用户在长时间使用电脑之后&#xff0c;时常会看到“暂存盘已满”的提示&#xff0c;这无疑会给后续的电脑使用带来烦恼&#xff0c;那么苹果电脑暂存盘已满怎么清理呢&#xff0c;下面将给大家带来一些干货帮你更好地解决这个问题。 CleanMyMac X2024全新版下载如下: h…

开源交互审计系统:功能强大、安全好用【送源码】

在当今信息化时代&#xff0c;网络安全越来越受到重视。传统的远程控制工具&#xff0c;如RDP、SSH、VNC等&#xff0c;虽然方便易用&#xff0c;但存在安全隐患&#xff0c;容易被黑客利用。很多时候我们都需要做一些防护的处理来来保障网络安全。 今天了不起来分享一款开源好…

27、Qt自定义标题栏

一、说明 QtWidget及其子类有默认的标题栏&#xff0c;但是这个标题栏不能美化&#xff0c;有时候满足不了我们的使用需求&#xff0c;所以进行自定义标题栏 二、下载图标 在下面的链接中下载两种颜色的最大化、向下还原、最大化和关闭八个图片&#xff0c;并找一张当做图标…

CellChat包文献介绍

Inference and analysis of cell-cell communication using CellChat - PubMed (nih.gov) 目录 在线数据 摘要 基础介绍 分析结果 1&#xff0c;概述 2&#xff0c;识别预测通路 3&#xff0c;连续的信号转导 4&#xff0c;预测空间共定位细胞群之间的关键信号转导事件…

numpy1

注意&#xff1a;reshape函数的 - 1&#xff08;是让电脑 自己计算的意思 import numpy as np n np.arange(0,25).reshape(5,5) m np.array([0,5,10,15,20])nn np.repeat(n,2,axis 1) m m.reshape(-1,1)nn[:,1:8:2] np.tile(m,(1,4)) nn[:,0:-1]

【计算机毕业设计】springboot果蔬种植销售一体化服务平台

伴随着我国社会的发展&#xff0c;人民生活质量日益提高。于是对果蔬种植销售一体化服务管理进行规范而严格是十分有必要的&#xff0c;所以许许多多的 信息管理系统应运而生。此时单靠人力应对这些事务就显得有些力不从心了。所以本论文将设计一套果蔬种植销售一体化服务平台&…

双向链表(详解)

在单链表专题中我们提到链表的分类&#xff0c;其中提到了带头双向循环链表&#xff0c;今天小编将详细讲下双向链表。 话不多说&#xff0c;直接上货。 1.双向链表的结构 带头双向循环链表 注意 这几的“带头”跟前面我们说的“头节点”是两个概念&#xff0c;实际前面的在…

35个矩阵账号,如何通过小魔推打造2704万+视频曝光?

在如今的短视频时代&#xff0c;矩阵发布的作用被发挥到极致&#xff0c;通过各个短视频平台的流量分发&#xff0c;虽然视频质量不如那些头部的IP&#xff0c;但是在视频数量上却能做到轻松碾压&#xff0c;让自己的品牌与门店有更多的声量&#xff0c;这就是如今短视频平台对…

2024/5/9 英语每日一段

With runoff from this year’s snow and rain boosting the levels of California’s reservoirs, state water managers on Tuesday announced plans to increase deliveries of supplies from the State Water Project to 40% of full allotments, up from 30% last month. …