13.进程---

news2024/11/17 17:22:48

一、进程的概念

1.可以用ps或top查看进程

2.pid=0;交换进程(作用是进程调度)
pid=1;init进程(作用是系统初始化)

3.getpid();//获取自身的进程标识符

4.getppid();//获取父进程的进程标识符
什么是父进程?
答:进程A创建了进程B,那么A叫做父进程,B叫做子进程。

二、进程的创建

使用fork函数创建一个进程,
pid_t fork(void),
fork函数调用成功,返回两次。
返回值为0,代表当前进程为子进程。
返回值为非负数,代表当前进程为父进程。
返回值为-1,代表调用失败。
(1)查看pid_t fork(void)函数原型,判断怎样使用该api.

man 2 fork

在这里插入图片描述发现需要2个头文件。
(2)调用api创建进程并查看其pid

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main(void)
{
	pid_t pid,pid1,pid2;
	char return_of_fork;
	pid1 = getpid();//pid of 1_creat_process.c
	
	printf("this is father process,pid = %d\n",pid1);

	return_of_fork = fork();
	

	if(return_of_fork > 0)
	{
		printf("this is father process,pid = %d\n",getpid());
	}
	else if(return_of_fork == 0)
	{
		printf("this is son process,pid = %d\n",getpid());
	}
	else if(return_of_fork < 0)
	{
		printf("fork failed\n");
	}

	return 0;
}

在这里插入图片描述
注意,执行完fork,
linux系统会为子进程拷贝一份文件(包括程序的正文,初始化的数据,未被初始化的数据,堆,栈)
然后运行父进程和子进程(进程调度),
运行父进程后,return_of_fork >0,并打印,
运行子进程后,return_of_fork =0,并打印,
*因此才能看到既满足 if(return_of_fork > 0),又满足 if(return_of_fork == 0); *
其实并不是同时满足,
上面提到,系统会为紫荆城拷贝一份文件,
在进程调度时,会分别执行父进程和子进程(用不太规范的话来描述:执行了2份main函数),
在父进程的调度中return_of_fork > 0并打印,
在子进程的调度中return_of_fork > 0==0并打印。

注意:向执行memcpy()时在地上申请空间
调用函数时,在栈上运行

三、创建进程时发生了什么

四、fork的应用场景

要求:父进程解析键盘输入的数值,当键盘输入的值为9时创建子进程并屏幕输出。

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main(void)
{
	char return_of_fork;
	int data = 1;
	while(1)
	{
		printf("please input a data\n");
		scanf("%d",&data);

		if(data == 9)
		{
			return_of_fork = fork();
			if(return_of_fork > 0)
			{
				printf("father process,pid = %d\n",getpid());
			}
			else if(return_of_fork == 0)
			{
				while(1)
				{
					printf("child process,pid = %d\n",getpid());
					sleep(1);
				}
		                
			}
		}
		else
		{
			printf("wait !  do nothing\n");
		}

	}
	return 0;
}

五、vfork和fork的区别

(1)直接使用父进程空间,不拷贝
(2)保证子进程优先运行,当子进程调用exit退出后,父进程才执行

六、进程的退出

  1. 种类:5种正常退出+3种异常退出
    (1)5种正常退出:
    main函数调用return;
    进程调用exit();
    进程调用_exit()或_Exit()
    进程最后1个线程返回;
    最后1个线程调用pthread_exit

(2)3种异常退出
调用adort;
当进程收到某些信号时;
最后1个线程对取消(cancellation)请求做出响应

七、父进程等待子进程退出

1.调用的api:
wait();//调用wait,可以防止子进程变成僵尸进程(子进程退出状态未被收集,则子进程会变为僵尸进程)
或waitpid();

man 2 wait

在这里插入图片描述
(1)wait()的使用方法,和常见使用场景
等待子进程的退出,并且收集子进程退出的状态(子进程正常退出和异常退出返回的状态不同)。
子进程的状态被返回给wait(int *wstatus)的参数

a)背景:忽略使用wait()时会导致子进程变成僵尸进程。
运行下面的代码,键盘输入9后后创建子进程,每隔1秒屏幕输出1次,打印三次后会exit子进程

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
int main(void)
{
	pid_treturn_of_fork;
	int cnt=0;
	int data = 1;
	return_of_fork = fork();
	while(1)
	{
		printf("please input a data\n");
		scanf("%d",&data);

		
			
			if(return_of_fork > 0)
			{
				while(1)
				{
				
				printf("father process,pid = %d\n",getpid());
				sleep(1);
				}
				
			}
			else if(return_of_fork == 0 && data == 9)
			{
				while(1)
				{
					
					
					printf("child process,pid = %d\n",getpid());
                                        sleep(1);
                                        cnt++;
					if(cnt ==3)
					{
					exit(0);
					}
				

				}
		                
			}
		
		else
		{
			printf("wait !  do nothing\n");
		}

	}
	return 0;
}

在这里插入图片描述
如图,键盘输入1后,一直调度父进程。
当键盘输入9后,开始调度子进程。子进程运行3次之后,子进程被结束。
在这里插入图片描述查看pid,发现子进程pid为22507,子进程变成僵尸进程了。
Z+指僵尸进程

b)使用wait()获取子进程退出状态,避免子进程变成僵尸进程
使用wait(NULL);(如果我们对这个子进程是如何死掉毫不在意,只想把这个僵尸进程消灭掉,(事实上绝大多数情况下,我们都会这样想),我们就可以设定这个参数为NULL)

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
int main(void)
{
	pid_t return_of_fork;
	int cnt=0;
	int data = 1;
	return_of_fork = fork();


	while(1)
	{
		    printf("please input a data\n");
		    scanf("%d",&data);
	
			if(return_of_fork > 0)
			{	
				wait(NULL);
				while(1)
				{
				
				printf("father process,pid = %d\n",getpid());
				sleep(1);
				}
				
			}
			else if(return_of_fork == 0 )
			{
				while(data == 9)
				{
					
					
					printf("child process,pid = %d\n",getpid());
                                        sleep(1);
                                        cnt++;
					if(cnt ==3)
					{
					exit(0);
					}
				

				}
		                
			}
		
		else
		{
			printf("wait !  do nothing\n");
		}

	}
	return 0;
}

在这里插入图片描述如图,使用wait(NULL),可以关掉僵尸进程
/------------/
在这里插入图片描述如图,使用WEXITSTATUS(status)可以查看子进程正常终止返回的状态;
使用方法如下:
int status_childProcess;
wait(&status_childProcess);
printf(“child process exit status:%d\n”,WEXITSTATUS(status_childProcess;));

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
int main(void)
{
	pid_t return_of_fork;
	int cnt=0;
	int data = 1;
	int status_childProcess;
	return_of_fork = fork();


	while(1)
	{
		        printf("please input a data\n");
		        scanf("%d",&data);

		
			
			if(return_of_fork > 0)
			{	
				wait(&status_childProcess);
				printf("child process exit status:%d\n",WEXITSTATUS(status_childProcess));
				while(1)
				{
				
				printf("father process,pid = %d\n",getpid());
				sleep(1);
				}
				
			}
			else if(return_of_fork == 0 )
			{
				while(data == 9)
				{
					
					
					printf("child process,pid = %d\n",getpid());
                                        sleep(1);
                                        cnt++;
					if(cnt ==3)
					{
					exit(1);
					}
				

				}
		                
			}
		
		else
		{
			printf("wait !  do nothing\n");
		}

	}
	return 0;
}

在这里插入图片描述如图所示配合wait()相关的宏,可以获得子进程退出状态。而且父进程是在子进程退出后才执行的。

(2)waitpid()的使用方法,和常见使用场景
在这里插入图片描述
在这里插入图片描述在这里插入图片描述

(3)孤儿进程
在这里插入图片描述
获取父进程的api:
getppid();
init进程的pid号==1

八、exec族函数

1.exec族函数中的函数调用失败时会设置error并返回-1,然后从源程序调用点接着往下执行。
执行成功后不会返回,也不会从源程序调用点接着往下执行。

函数原型:


int execl(const char *path, const char *arg, ...);

int execlp(const char *file, const char *arg, ...);

int execle(const char *path, const char *arg, ..., char * const envp[]);

int execv(const char *path, char *const argv[]);

int execvp(const char *file, char *const argv[]);

参数


path参数表示你要启动程序的名称包括路径名

arg参数表示启动程序所带的参数,一般第一个参数为要执行命令名,不是带路径且arg必须以NULL结束

返回值:成功返回0,失败返回-1

2.其他知识
(1)如何查看linux指令所在路径
在这里插入图片描述如图,date指令用于查看系统时间。
ls指令用于查看该路径下的文件。
whereis用于获取linux指令的路径。

如上图所示,ls所在路径为“/bin/ls”,现在要求用execl调用ls.
程序如下

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(void)
{
	printf("before exec\n");
	if(execl("/bin/ls","ls","-l",NULL) == -1)//exec族函数中的函数调用失败时会设置error并返回-1,然后从源程序调用点接着往下执行。执行成功后不会返回,也不会从源程序调用点接着往下执行。
	{
		printf("exec failed\n");
	}
	printf("after exec\n");
}

运行结果:在这里插入图片描述如图运行成功,execl调用了ls.
调用成功,不返回-1,不执行 printf(“exec failed\n”);
调用成功,也没有继续往下执行,即不执行 printf(“after exec\n”);

若调用失败,则如图所示(失败的原有是 ls的路径不对)
在这里插入图片描述

(2)怎样查看环境变量
在这里插入图片描述

(3)怎样配置临时环境变量(临时环境变量的生存周期在该终端框被关闭时结束)
在这里插入图片描述先使用pwd查看当前路径,
再使用export PATH=
"="后面的参数¥PATH是指原先的环境变量。
添加好临时环境变量后就可以在别的路径下调用这里的可执行文件。
例如myechoarg是可执行文件,在配置环境变量前myechoarg只能在这个路径执行,
配置环境变量后,就可以在任意路径下执行。

(4)perror();的用法
(5)

九、system

system()是封装后的execl();
system()和execl()的区别是:system执行后,会从源程序调用点继续往下执行。
函数原型:

如图,是system的使用方法,system的参数是可执行文件的路径
在这里插入图片描述在本路径下,有4个文件
main.c编译生成的目标文件是work,其运行结果是:屏幕输出hello
my_system.c是调用system()的demo,其编译生成目标文件是myrun,运行结果是"执行work文件"

补充:可直接调用shell指令
如图,调用ls
在这里插入图片描述

十、popen

popen和system相比,
有1个好处,
即:可以获得运行的结果

函数原型
在这里插入图片描述其返回值为FILE型,

#include <stdio.h>
#include <stdlib.h>

int main()
{
	char return_buffer[1024] = {0};
	FILE *fp;
	fp = popen("ps","r");

	int nread = fread(return_buffer,1,1024,fp);
	printf("return_buffer %d byte,buffer:%s\n",nread,return_buffer);
	return 0;
}

在这里插入图片描述如图,popen的返回值是运动的结果;

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

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

相关文章

【GStreamer 】 TX1中CPU和GPU解码显示海康相机RTSP流

大家好&#xff0c;我是虎哥&#xff0c;今天找了一套海康的相机&#xff0c;想后续测试一下DeepStream用网络相机RTSP流做输入看看后续目标识别和分类。但是还是想先实时看看视频&#xff0c;当然&#xff0c;可以选择VLC去查看&#xff0c;顺道我也用GStreamer 来测试了一下&…

HashMap原理详解

一、hashmap简介 hashmap是Java当中一种数据结构&#xff0c;是一个用于存储Key-Value键值对的集合&#xff0c;每一个键值对也叫作Entry。 二、JDK7的HashMap1、JDK7时HashMap的数据结构 1、在JDK7之前&#xff0c;hashmap底层采用数组链表的数据结构来存储数据 2、插入数据采…

SpringBoot静态资源访问

静态资源路径 类路径下&#xff1a;/resources/static/、/resources/public/、/resources/resources/、/resources/META-INF/resources 这些路径下的资源均可直接访问&#xff1b;通过 http://ip:port/资源名称 访问即可 可在配置文件中对访问路径和访问拦截规则进行设置&…

【ArcGIS Pro二次开发】(5):UI管理_自定义控件的位置

新增的自定义控件一般放在默认的【加载项】选项卡下&#xff0c;但是根据需求&#xff0c;我们可能需要将控件放在新的自定义选项卡下&#xff0c;在自定义选项卡添加系统自带的控件&#xff0c;将自定义的按钮等控件放在右键菜单栏里以方便使用&#xff0c;等等。 下面就以一…

Maven:工程的拆分与聚合

Maven 拆分与聚合创建父工程创建子模块pom.xml配置示例拆分与聚合 在 Maven 中, 拆分是将一个完整的项目分成一个个独立的小模块,聚合是将各个模块进一步组合,形成一个完整的项目。接下来简单示例拆分与聚合的过程。 创建父工程 父工程,一个pom工程,目录结构简单,只需有…

cocos2dx 4.0 - cpp - pc版 环境搭建

开发环境vs2022 cocos2dx4.0 python2.7.18 cmake3.25安装教程&#xff08;环境搭建&#xff09;安装VS2022-Community&#xff0c; 勾选c进行安装安装cmake3.25, 勾选环境变量进行安装安装python2.7.18, 勾选环境变量进行安装下载cocos2dx4.0并解压配置cocos2dx:运行cmd,进入…

DCL 数据控制语言

1、简介 DCL英文全称是Data Control Language(数据控制语言)&#xff0c;用来管理数据库用户、控制数据库的访问权限。 2、管理用户 2.1 查询用户 select * from mysql.user;查询的结果如下: 其中 Host代表当前用户访问的主机, 如果为localhost, 仅代表只能够在当前本机访问…

Nuxtjs

SSR渲染 SSR&#xff1a;在服务器端将Vue渲染成HTML返回给浏览器 优点 对SEO支持好SPA单页渲染更快 npx create-nuxt-app nuxtDemo 修改开发地址 package.json文件中进行修改 "config":{"nuxt":{"host":"127.0.0.1","port…

朋友当上项目测试组长了,我真的羡慕了

最近我发现一个神奇的事情&#xff0c;我一个朋友居然已经当上了测试项目组长&#xff0c;据我所知他去年还是在深圳的一家创业公司做苦逼的测试狗&#xff0c;短短8个月&#xff0c;到底发生了什么&#xff1f; 于是我立刻私聊他八卦一番。 原来他所在的公司最近正在裁员&am…

01_Docker 简介

01_Docker 简介 文章目录01_Docker 简介1.1 Docker 简介1.2 Docker 组件1.2.1 Docker 客户端和服务区1.2.2 Docker 镜像1.2.3 Registry1.2.4 Docker 容器参考资料https://www.runoob.com/docker/ubuntu-docker-install.html 1.1 Docker 简介 Docker 是一个能够把开发的应用程…

HTML+CSS+JavaScript学习笔记~ 从入门到精通!

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录前言一、HTML1. 什么是HTML&#xff1f;一个完整的页面&#xff1a;<!DOCTYPE> 声明中文编码2.HTML基础①标签头部元素标题段落注释水平线文本格式化②属性3.H…

SOFA Weekly|开源人、本周贡献 issue 精选

SOFA WEEKLY | 每周精选 筛选每周精华问答&#xff0c;同步开源进展欢迎留言互动&#xff5e;SOFAStack&#xff08;Scalable Open Financial Architecture Stack&#xff09;是蚂蚁集团自主研发的金融级云原生架构&#xff0c;包含了构建金融级云原生架构所需的各个组件&#…

Docker安装Tomcat、mysql、redis

目录 前言 一、安装Tomcat 二、安装mysql &#xff08;一&#xff09;简单版 &#xff08;二&#xff09;实战版 三、安装redis 前言 镜像可以先去Docker Hub Container Image Library | App Containerization 左上角搜&#xff0c;然后点进入可以看到具体的命令&#…

网络协议(TCP/IP)

目录一、网络分层模型二、OSI模型三、网络传输原理四、TCP/IP1、TCP/IP 原理2、TCP 三次握手/四次挥手3、Http协议和TCP/IP的区别五、HTTP原理六、HTTPS原理七、CDN原理一、网络分层模型 互联网的本质就是一系列的网络协议&#xff0c;最早由ISO国际组织定义为7层网络参考模型…

【JS】数组常用方法总结-功能、参数、返回值

数组常用方法总结-功能、参数、返回值 用简单的js示例 运行在线工具&#xff1a;链接: 菜鸟工具 菜鸟工具示意图&#xff1a; ![在这里插入图片描述](https://img-blog.csdnimg.cn/de8589eb1acf42abb0347d8a3a3bbdfa.png 1.会改变原有数组方法 &#xff08;1&#xff09;pu…

(考研湖科大教书匠计算机网络)第五章传输层-第三节:TCP和UDP对比

获取pdf&#xff1a;密码7281专栏目录首页&#xff1a;【专栏必读】考研湖科大教书匠计算机网络笔记导航 文章目录一&#xff1a;TCP和UDP概述二&#xff1a;TCP和UDP对比本节对应视频如下 【计算机网络微课堂&#xff08;有字幕无背景音乐版&#xff09;】&#xff1a;TCP和UD…

ShowCase 专治开发的「我自测好了」

背景 开发提测时信心十足的说我自测过了肯定没问题&#xff0c;结果分分钟打脸&#xff0c;测试在测试环境一测就发现xx「功能」不可用、xx「流程」阻塞 产品验收在测试之后&#xff0c;导致验收的时候可能出现与设计不一致&#xff0c;造成返工成本和风险加大 1.开发自测质量…

常用聚类算法分析

1. 什么是聚类 1.1. 聚类的定义 聚类(Clustering)是按照某个特定标准(如距离)把一个数据集分割成不同的类或簇&#xff0c;使得同一个簇内的数据对象的相似性尽可能大&#xff0c;同时不在同一个簇中的数据对象的差异性也尽可能地大。也即聚类后同一类的数据尽可能聚集到一起…

Kubernetes 1.18学习笔记

文章目录一、Kubernetes 概述和架构1、kubernetes 基本介绍2、Kubernetes 功能3、Kubernetes 架构组件4、Kubernetes 核心概念5、Kubernetes 工作原理二、Kubernetes 集群搭建1、系统环境准备1.1 安装要求1.2 系统初始化2、客户端工具kubeadm搭建2.1 安装步骤2.2 安装组件2.3 集…

MongoDB数据存储格式

前言 之前分享了MongoDB的基本命名和视图等信息&#xff0c;本文分享一下MongoDB的数据存储类型&#xff0c;使用方式。基础的MongoDB信息就学习完啦&#xff0c;之后会继续分享MongoDB进阶的一些东西。 MongoDB数据存储格式前言1 文件结构1.2 字段名称2 点符号2.2 嵌入式文件…