进程大杂烩

news2024/10/7 12:29:44

1、fork函数的使用

使用fork()函数创建一个进程
pid_t fork(void)
fork函数调用成功,返回两次
返回为0, 代表当前进程是子进程
返回为正数,代表当前进程为父进程

fork()函数运行后会创建一个进程,加上开始的进程一共有两个进程,会执行两次fork()函数之后的内容,两次的区别是pid号不同
 
  1 #include <sys/types.h>
  2 #include <unistd.h>
  3 #include <stdio.h>
  4 int main()
  5 {
  6         pid_t pid;
  7         pid_t pid2;
  8         pid = getpid();
  9
 10         printf("before fork, pid :%d\n", pid);
 11
 12         fork();
 13
 14         pid2 = getpid();
 15
 16         if (pid == pid2)
 17         {
 18                 printf("this is father, pid :%d\n", pid2);
 19         }
 20         else{
 21
 22                 printf("this is child, pid :%d\n", pid2);
 23         }
 24         return 0;
 25 }

在这里插入图片描述

  1 #include <sys/types.h>
  2 #include <unistd.h>
  3 #include <stdio.h>
  4 int main()
  5 {
  6         pid_t pid;
  7
  8         printf("father pid :%d\n", getpid());
  9
 10         pid = fork();
 11
 12
 13         if (pid > 0)
 14         {
 15                 printf("this is father, pid :%d\n", getpid());
 16         }
 17         else if(pid == 0) {
 18                 printf("this is child, pid :%d\n", getpid());
 19         }
 20         return 0;
 21 }

在这里插入图片描述

2、进程创建发生了什么事

发生了:将父进程的内容复制一份给子进程
在传统内核中,是复制P1的代码段,数据段,堆,栈这四个部分,注意是其内容相同。(拷贝一模一样的)
在这里插入图片描述

写时拷贝:(copy on wirte)
内核只为新生成的子进程创建虚拟空间结构,它们复制于父进程的虚拟空间结构,但是不为它们分配内存,而是共享父进程的物理内存,当父子进程有更改相应段的行为发生时,再为子进程相应段分配物理内存。

3、vfork函数创建进程

与fork的区别:
1、vfork使用父进程存储空间,不拷贝
2、vfork保证子进程先运行,当子进程调用exit()推出后,父进程才执行

先用fork创建一次进程,例如:

 1 #include <sys/types.h>
  2 #include <unistd.h>
  3 #include <stdio.h>
  4 int main()
  5 {
  6         pid_t pid;
  7
  8         pid = fork();
  9
 10
 11         if (pid > 0)
 12         {
 13                 while(1)
 14                 {
 15                         printf("this is father, pid :%d\n", getpid());
 16                         sleep(1);
 17                 }
 18         }
 19         else if(pid == 0)
 20         {
 21                 while(1)
 22                 {
 23                         printf("this is child, pid :%d\n", getpid());
 24                         sleep(1);
 25                 }
 26         }
 27         return 0;
 28 }
~

在这里插入图片描述
结果是father、child进程彼此争夺CPU,在彼此while(1)不断循环

现在用vfork()创建进程,例如:

  1 #include <sys/types.h>
  2 #include <unistd.h>
  3 #include <stdio.h>
  4 #include <stdlib.h>
  5 int main()
  6 {
  7         pid_t pid;
  8         int cnt = 0;
  9         pid = vfork();
 10
 11         if (pid > 0)
 12         {
 13                 while(1)
 14                 {
 15                         printf("cnt=%d\n", cnt);
 16                         printf("this is father, pid :%d\n", getpid());
 17                         sleep(1);
 18                 }
 19         }
 20         else if(pid == 0)
 21         {
 22                 while(1)
 23                 {
 24                         printf("this is child, pid :%d\n", getpid());
 25                         sleep(1);
 26
 27                         if (++cnt == 3)
 28                         {
 29                                 exit(0);
 30                         }
 31                 }
 32         }
 33         return 0;
 34 }

在这里插入图片描述
可见前期一直是子进程运行,运行三次后调用exit(0);正常退出后才轮到父进程运行,且在子进程里面修改的cnt的值在父进程中也“同步”修改,但并不是同步,是父子进程共用存储空间

4、进程退出

正常退出:
1、main函数调用return;
2、进程调用exit(0);标准C库;
3、进程调用_exit();或者_Exit(),属于系统调用;

补充:
1、进程最后一个线程返回
2、最后一个线程调用pthread_exit

异常退出:
1、调用abort
2、当进程收到某些信号时,如ctrl+c
3、最后一个线程对取消(cancellation)请求做出响应

5、父进程等待子进程退出(一)

父进程等待子进程退出
并收集子进程的退出状态

在这里插入图片描述

子进程退出状态不被收集,变成僵死进程(僵尸进程),状态是Z+(zombie)

父进程收集子进程退出状态,相关函数:
在这里插入图片描述

status参数:是一个整型数指针
非空:子进程退出状态放在它所指向的地址中
空: 不关心退出状态

代码实现一下:

  1 #include <sys/types.h>
  2 #include <unistd.h>
  3 #include <stdio.h>
  4 #include <stdlib.h>
  5 int main()
  6 {
  7         pid_t pid;
  8         int cnt;
  9         pid = fork();
 10
 11         if (pid > 0)
 12         {
 13                 while(1)
 14                 {
 15                         wait(NULL);///
 16                         printf("cnt=%d\n", cnt);
 17                         printf("this is father, pid :%d\n", getpid());
 18                         sleep(1);
 19                 }
 20         }
 21         else if(pid == 0)
 22         {
 23                 while(1)
 24                 {
 25                         printf("this is child, pid :%d\n", getpid());
 26                         sleep(1);
 27
 28                         if (++cnt == 3)
 29                         {
 30                                 exit(0);
 31                         }
 32                 }
 33         }
 34         return 0;
 35 }

在这里插入图片描述

加入了wait(NULL)等待,父进程就会一直阻塞,等待子进程退出后再运行,但是不会收集子进程的状态码,

如果我们想要知道子进程的退出码怎么办呢:

 #include <sys/types.h>
 #include <unistd.h>
 #include <stdio.h>
 #include <stdlib.h>
 int main()
{
           pid_t pid;
           int cnt;
           int status; /
           pid = fork();
 
          if (pid > 0)
          {
                  while(1)
                  {
                          wait(&status);/
                          printf("status = %d\n", status);/
                          printf("cnt=%d\n", cnt);
                          printf("this is father, pid :%d\n", getpid());
                          sleep(1);
                }
          }
          else if(pid == 0)
          {
                  while(1)
                  {
                          printf("this is child, pid :%d\n", getpid());
                          sleep(1);
 
                          if (++cnt == 3)
                          {
                                  exit(3);//
                          }
                  }
          }
          return 0;
}

在这里插入图片描述
我们在exit()里面写的退出码是3,但是通过wait获取的状态码并不是3,这是为什么呢
要想得到状态码,要通过宏来解析它

用于检查 wait() 和 waitpid() 两个函数返回终止状态的宏: 这两个函数返回的子进程状态都保存在status指针中,用以下3个宏可以检查该状态:
WIFEXITED(status): 若为正常终止, 则为真。此时可执行 WEXITSTATUS(status): 取子进程传送给exit或_exit参数的低8位.
WIFSIGNALED(status): 若为异常终止, 则为真。此时可执行 WTERMSIG(status): 取使子进程终止的信号编号.
WIFSTOPPED(status): 若为当前暂停子进程, 则为真。此时可执行 WSTOPSIG(status): 取使子进程暂停的信号编号

printf("status = %d\n", status);
改写为:
printf("status = %d\n", WEXITSTATUS(status));

在这里插入图片描述

6、父进程等待子进程退出(二)

再来细说wait()函数
在这里插入图片描述

如果其所有子进程都还在运行,则阻塞
如果一个子进程已终止,正等待父进程获取其终止状态,则取得该子进程的终止状态立即返回
如果它没有任何子进程,即立即出错返回

wait()与waitpid()的区别:
wait()使调用者阻塞
waitpid()有一个选项,可以使调用者不阻塞

对于waitpid()的参数:

参数值说明
pid<-1等待进程组号为pid绝对值的任何子进程。
pid=-1等待任何子进程,此时的waitpid()函数就退化成了普通的wait()函数。
pid=0等待进程组号与目前进程相同的任何子进程,也就是说任何和调用waitpid()函数的进程在同一个进程组的进程。
pid>0等待进程号为pid的子进程。
参数说明
WNOHANG如果pid指定的子进程没有结束,则waitpid()函数立即返回0,而不是阻塞在这个函数上等待;如果结束了,则返回该子进程的进程号。
WUNTRACED如果子进程进入暂停状态,则马上返回。

但是调用waitpid(),并且使用WNOHANG 参数的话,虽然父进程不会阻塞等待子进程结束,但是等子进程结束后会变成僵尸进程

7、孤儿进程

父进程如果不等待子进程退出,在子进程之前就结束了总结的生命,此时的子进程叫做孤儿进程
Linux避免系统存在过多孤儿进程,init进程收留孤儿进程,变成孤儿进程的父进程

8、exec族函数

exec族函数相当于就是调用打包好的程序,执行一个shell指令,详情可见博文

在A进程可以启动B进程,跳到B进程去执行

9、system函数

https://www.cnblogs.com/leijiangtao/p/4051387.html

10、popen()函数

https://blog.csdn.net/libinbin_1014/article/details/51490568

比system的好处:可以获取运行的输出结果

 #include <sys/types.h>
 #include <unistd.h>
 #include <stdio.h>
 #include <stdlib.h>
 int main()
{
          char ret[1024] = {0};
          FILE *fp;

          fp = popen("ps", "r");
          int nread = fread(ret, 1, 1024, fp);//读进ret数组,一次读一个,读1024次,从fp里面读

          printf("read ret %d byte, ret=%s\n", nread, ret);
          return 0;
}

在这里插入图片描述

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

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

相关文章

第一天总结 之 用户管理界面的实现 之 模糊查询和分页操作

第一天总结 之 用户管理界面的实现 之 模糊查询和分页操作 1、明确页面的跳转 当登录操作执行时 如果正确 跳转到 UserFuzzySelectServlet 即用户模糊查询的select 注&#xff1a;因为第一次写项目 对于很多操作都不熟悉 很多前期操作没 有 按着 见名之意 …

迎兔年 贺新春 | vLive虚拟直播新年场景上线!

为了带来更为舒适的用户体验给用户提供更好的线上活动品质vLive虚拟直播2.3.1版本进行了优化升级还有多个新春场景上新全新升级的vLive又增添了哪些亮点一起来快速了解一下吧场景上新&#xff1a;新春活动更出彩农历新春降至如何让拜年视频更出众&#xff1f;如何让新年直播更精…

【C++】为什么C++会支持函数重载

文章目录 函数重载 1.概念 2.支持函数重载的原理 2.1准备知识 2.2原理 函数重载 1.概念 在C语言中&#xff0c;是不允许同名函数存在的。但是在一个作用域种&#xff0c;比如加法函数&#xff0c;想要实现各种类型的数据相加&#xff0c;要定义多个函数&#xff0c;但是…

设计模式-七大原则

设计模式 聚合 设计模式追求的是 1.代码重用性&#xff08;相同功能的代码不用重复编写&#xff09; 2.可读性&#xff08;规范性&#xff0c;便于其他程序员阅读和理解&#xff09; 3.可扩展性&#xff08;增加新的功能非常方便&#xff09; 4.可靠性&#xff08;增加新的…

【国产可编程逻辑控制器plc调研】

国产可编程逻辑控制器plc调研1 高性能PLC&#xff08;ACxxx系列&#xff09;2 中型PLC&#xff08;AMx00系列&#xff09;3 小型PLC&#xff08;HxU、HxS&#xff09;4 小型紧凑型PLC&#xff08;Easy&#xff09;[新品]总结由于有国产化的需求&#xff0c;所以调研了一家国内的…

Internet Download Manager2023下载器Win系统经典下载工具

IDM下载器是一款非常经典的多线程下载工具&#xff0c;广受国内外用户喜爱。该软件专注于文件下载&#xff0c;没有任何多余功能&#xff0c;也没有烦人的弹窗广告打扰&#xff0c;简单易操作。特别是站点抓取功能&#xff0c;对于网站整站下载非常的好用。 整站下载器有很多&…

shell-将密码输入错误超过4次的IP地址通过firewalld防火墙阻止访问

应用场景&#xff1a;防止恶意IP尝试ssh登录 脚本说明&#xff1a;将密码输入错误超过四次得ip地址通过iptable防火墙访问。 分析&#xff1a; 首先&#xff0c;需要知道ssh远程访问记录在哪一个文件中 /var/log/secure其次&#xff0c;模拟远程访问输错密码&#xff0c;查…

数字化+智能化,低代码平台助力能源行业创新赋能

编者按&#xff1a;能源行业数字化转型需求发杂&#xff0c;定制化要求高&#xff0c;低代码平台对于能源行业来说可谓是“专业对口”。本文分析了能源行业数字化转型的痛点和需求&#xff0c;并进一步指出低代码平台的在能源行业中的应用价值&#xff0c;最后介绍了老牌低代码…

破解版IDM导致电脑反复闪屏的解决方案

破解版IDM导致电脑反复闪屏的解决方案 概括&#xff1a; 进入安全模式&#xff0c;卸载IDM&#xff0c;结束 文章目录破解版IDM导致电脑反复闪屏的解决方案问题原因解决方式&#xff1a;问题原因 在使用IDM(Internet Download Manager)的破解版下载文件时突然电脑闪屏&#…

分享5款开年必备的工具软件

最近陆陆续续收到好多小伙伴的咨询&#xff0c;这边也是抓紧时间整理出几个好用的软件&#xff0c;希望可以帮到大家。 1. 影像处理——GIMP GIMP 提供了各种的影像处理工具&#xff0c;滤镜&#xff0c;还有许多的组件模块&#xff0c;对于要制作一个又酷又炫的网页按钮或网…

华为机试题:HJ15 求int型正整数在内存中存储时1的个数(python)

文章目录知识点详解1、input()&#xff1a;获取控制台&#xff08;任意形式&#xff09;的输入。输出均为字符串类型。2、print() &#xff1a;打印输出。3、int() &#xff1a;将一个字符串或数字转换为十进制整数&#xff08;强转&#xff09;。输入可以指定进制&#xff0c;…

JUC面试(二)——JUCJMMvolatile 2.0

JUC&JMM JMM 不保证原子性 各个线程对主内存中共享变量的操作都是各个线程各自拷贝到自己的工作内存进行操作后在写回到主内存中的。 这就可能存在一个线程AAA修改了共享变量X的值&#xff0c;但是还未写入主内存时&#xff0c;另外一个线程BBB又对主内存中同一共享变量…

【项目实战】基于XStream实现漏洞信息数据(XML格式)的手动导入功能

一、背景 项目中需要实现漏洞信息数据的手动导入功能 以下是导入的XML文件所在地址&#xff1a;https://www.cnnvd.org.cn/home/loophole 二、实现思路 &#xff08;1&#xff09;前端实现&#xff08;ElementUIAvue&#xff09; &#xff08;2&#xff09;后端实现 三、…

一文读懂eslint和prettier

为什么会有eslint和prettier&#xff0c;他们有什么作用 首先&#xff0c;工具的出现都是为了解决一定的问题。 团队写代码风格不一样&#xff0c;书写方式不一致&#xff0c;导致整个项目同一类型代码出现多种写法&#xff0c;或者不严谨、或者不美观。或者是提交git时&#…

秒杀功能、高并发系统关注的问题、秒杀系统设计-59

一&#xff1a;秒杀 1.1 特点 秒杀具有瞬间高并发的特点&#xff0c;针对这一特点&#xff0c;必须要做限流 异步 缓存 &#xff08; 页面静态化&#xff09;。 1.2 限流方式 前端限流&#xff0c;一些高并发的网站直接在前端页面开始限流&#xff0c;例如&#xff1a;小…

Python 生成 svg 图片,一篇博客带你掌握 Python 与 svg 之间的操作

python svgwritePython 操作 SVG 图片的库清单svgwrite 库svgwrite 库其他图形绘制储备反爬技术 svgwrite 生成一个手机号Python 操作 SVG 图片的库清单 在 Python 中&#xff0c;可以使用以下几种库来生成 SVG 图片&#xff1a; svgwrite&#xff1a;这是一个简单易用的 Pyt…

民生银行联手火山引擎,一场“1+1>2”的金融数字化征程

数字化时代下&#xff0c;信息成为企业生长的升维秘钥。管理学者德鲁克在《21世纪的管理挑战》一书中指出&#xff0c;我们正经历着一场信息革命。其中特别提出&#xff0c;不是某种软硬件的革命&#xff0c;而是“信息”被使用和利用的方式转变了。近年来&#xff0c;金融行业…

【终极UI/UX工具包】上海道宁与Infragistics助力您简化程序开发,​创建精美应用程序

​​​​​​​​​​​​​​ Infragistics Ultimate是 开发者的UI/UX工具包 可以简化程序开发 加速从设计到代码的应用程序创建 为Web、移动和桌面 创建精美应用程序所需的一切帮助 Infragistics Ultimate附带 完整的企业级.NET和JavaScript图表 网格和UI组件以及可用…

SQL--DML

目录 1、添加数据&#xff08;insert&#xff09; 1. 给指定字段添加数据 2. 给全部字段添加数据 3. 批量添加数据 2、修改数据&#xff08;update&#xff09; 3、删除数据&#xff08;delete&#xff09; DML英文全称是Data Manipulation Language(数据操作语言)&…

AIParsing(TIP2022)-人体解析论文阅读

文章目录解决问题算法人体解析AIParsingFPN检测头边缘引导解析头实验结论论文&#xff1a; 《AIParsing: Anchor-Free Instance-Level Human Parsing》github&#xff1a; https://github.com/31sy/AIParsing解决问题 目前SOTA实例级人体解析模型使用二阶段基于anchor的检测器…