Linux进程编程2——与“进程”相关的API

以下内容源于网络资源的学习与整理,如有侵权请告知删除。

一、fork()函数:父进程创建子进程

函数原型

所需头文件        

#include <unistd.h>

#include <sys/types.h>

函数原型pid_t fork(void);
返回值在子进程中返回0,在父进程中返回子进程的PID,失败则返回一个负值。

函数作用

fork()函数用于从已经存在的进程中创建一个新进程。新进程叫做子进程,原进程叫做父进程。子进程是父进程的一个复制品,它从父进程继承整个进程的地址空间(每个进程的地址空间是独立的),包括进程上下文、代码段、进程堆栈、内存信息、打开的文件描述符、信号控制设定、进程优先级、进程组号、当前工作目录、根目录、资源限制和控制终端等等,子进程所独有的只有其进程号、资源使用和计时器等等。

补充说明

1、使用fork()的典型方法

使用fork()后用 if 判断返回值,如果返回值大于0时就是在父进程中,等于0就是在子进程中,然后在各自的{ }里做操作。

2、fork()创建进程的方式

操作系统利用已有的进程,来复制生成一个新的进程。因为重新创建进程的代价很大。

3、父进程与子进程的关系

子进程一旦建立,子进程不再依赖于父进程。子进程有自己独立的PCB,被内核同等调度。

4、fork()的返回值情况

fork函数调用一次,会返回两次,因为父子都有相同的一份代码,进程同时被运行。fork函数在父进程中返回子进程的PID;在子进程中返回0。

代码示例

p1 =fork();if(p1=0) //子进程
{printf("hello word,pid = %d \n",getpid());
}if(p1>0) //父进程
{printf("hello word,pid = %d \n",getpid());
}

二、exec函数族:在进程中启动另一个程序

函数原型

所需头文件        

#include <unistd.h>

函数原型int execl(const char *path, const char *arg, ...);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg,..., char * const envp[]);
int execvpe(const char *file, char *const argv[],char *const envp[]);

函数作用

execl函数族用于在进程中启动另一个可执行文件,可以根据指定的文件名或者目录名找到可执行文件,并用它来替代调用这个函数的进程的数据段、代码段和堆栈段,在执行完之后,原调用进程的内容除了进程号,其他内容均被新进程替换。

补充说明

1、为什么需要excel函数族?

fork()创建子进程后,子进程可以独立执行一个新的程序,比如可以在子进程 if(){ } 中写入新程序的代码。但是这样操作不够灵活,因为它需要我们键入源代码,这意味着我们必须知道源代码。对于一些没有源代码而只有编译后的可执行程序(比如 ls -la 命令),就不能使用这种方式。而使用exec族函数,可以直接把一个编译好的可执行程序直接加载运行。

2、excel函数族的应用场景

(1)进程可以调用excel函数族中任意一个函数让自己重生。

(2)如果想进行多进程运行,则父进程先调用fork()函数创建一个子进程,在子进程里使用execl函数族中的任意一个函数来执行一个可执行程序。

代码示例

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>  
#include <sys/wait.h>
#include <stdlib.h>int main(void)
{pid_t pid = -1;pid_t ret = -1;int status = -1;pid = fork();if (pid > 0)  // 父进程{printf("parent, 子进程id = %d.\n", pid);}else if (pid == 0) // 子进程{//execl("/bin/ls", "ls", "-l", "-a", NULL);		// ls -l -a//char * const arg[] = {"ls", "-l", "-a", NULL};//execv("/bin/ls", arg);//execl("hello", "aaa", "bbb", NULL);//char * const arg[] = {"aaa", "bbb", NULL};//execv("hello", arg);//execlp("ls", "ls", "-l", "-a", NULL);	char * const envp[] = {"AA=aaaa", "XX=abcd", NULL};execle("hello", "hello", "-l", "-a", NULL, envp);return 0;}else{perror("fork");return -1;}return 0;
}

三、exit()函数:终止进程

函数原型

所需头文件        

#include <stdlib.h>

函数原型void exit(int status);
返回值status是一个整型参数,利用这个参数可以传递进程结束时的状态。一般来说,0表示正常结束,其他数字表示出现了错误,进程非正常结束。在实际编码中,可以利用wait()函数接收子进程的返回值,从而针对不同的情况进行不同的处理。

函数作用

exit()函数用来终止进程。当调用此函数时,进程会无条件地停止剩余操作,终止本进程的运行。

补充说明

无。

四、wait()函数:父进程回收子进程

函数原型

所需头文件        

#include <sys/wait.h>

#include <sys/types.h>

函数原型 pid_t wait(int *status);
参数说明这里的status是一个整型指针,是该子进程退出时的状态。若status不为空,则通过它可以获得子进程的结束状态。另外,子进程的结束状态可由Linux中的一些特定的宏来检测。
返回值成功返回已经结束的子进程的的进程号。失败则返回-1。

函数作用

wait()函数主要用来回收子进程的资源,同时获取被回收的子进程的进程号与退出状态。

补充说明

(1)wait()函数的返回值

成功则返回本次被回收的子进程的进程号。当前进程可能有多个子进程,wait()函数的返回值可以用来判断哪一个子进程被回收了。

(2)wait()函数的工作原理

父进程调用wait函数后会进入阻塞。当子进程结束时,系统向其父进程发送SIGCHILD信号,父进程被SIGCHILD信号唤醒后,会去回收僵尸子进程。若父进程没有任何子进程,或者子进程已经结束,则wait立即返回。父子进程之间是异步的,SIGCHILD信号机制就是为了解决父子进程之间的异步通信问题,让父进程及时地回收僵尸子进程。

(3)检测子进程退出状态的宏

  • WIFEXITED:用来判断子进程是否正常终止(return、exit、_exit退出);
  • WIFSIGNALED:用来判断子进程是否非正常终止(被信号所终止);
  • WEXITSTATUS:用来得到正常终止情况下的进程返回值。

代码示例

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>  
#include <sys/wait.h>
#include <stdlib.h>int main(void)
{pid_t pid = -1;pid_t ret = -1;int status = -1;pid = fork();if (pid > 0){// 父进程//sleep(1);printf("parent.\n");ret = wait(&status);printf("子进程已经被回收,子进程pid = %d.\n", ret);printf("子进程是否正常退出:%d\n", WIFEXITED(status));printf("子进程是否非正常退出:%d\n", WIFSIGNALED(status));printf("正常终止的终止值是:%d.\n", WEXITSTATUS(status));}else if (pid == 0){// 子进程printf("child pid = %d.\n", getpid());return 51;//exit(0);}else{perror("fork");return -1;}return 0;
}

五、getpid()函数:获取当前进程的进程号

函数原型

所需头文件        

#include <sys/types.h>

#include <unistd.h>

函数原型

pid_t getpid(void);//获取当前进程的进程号

(pid_t getppid(void);//获取当前进程的父进程的进程号)

返回值返回值表示当前进程的进程号。

函数作用

getpid()函数用来获取当前进程的进程号。

补充说明

在shell命令行中执行某个程序,程序中获取当前进程的父进程的进程号,会发现脚本进程bash就是当前进程的父进程。

xjh@ubuntu:~/iot/tmp$ ./a.out 
pid = 4963 
parent id = 3009            //获取当前进程的父进程的进程号,得到3009
xjh@ubuntu:~/iot/tmp$ psPID TTY          TIME CMD3009 pts/0    00:00:01 bash4964 pts/0    00:00:00 ps  //bash这个脚本进程的进程号,是3009
xjh@ubuntu:~/iot/tmp$ cat test.c
#include<stdio.h>
#include <sys/types.h>
#include <unistd.h> int main(int argc, char **argv)
{pid_t p1=-1,p2=-2;p1=getpid();p2=getppid();printf("pid = %d \n", p1);printf("parent id = %d \n",p2);return 0;
}
xjh@ubuntu:~/iot/tmp$ 

六、system()函数:执行某命令

函数原型

所需头文件#include <stdlib.h>
函数原型int system(const char *command);
返回值        命令执行成功返回0,执行失败返回-1。

函数作用

执行 Shell 命令,其中command为命令名。

补充说明

system函数会调用fork函数产生子进程,由子进程来执行command命令,命令执行完后随即返回原调用的进程。也就是说,system()函数等价于fork()函数+execl族其中一个函数。

代码示例

#include <stdio.h>
#include<string.h>
#include<stdlib.h>
int main(void)
{char input[100];system("shutdown -h 1 &");//这是linux系统下的一个关机命令printf("你的电脑将在一分钟后关机,如果输入“我是猪”,就会取消关机!\n请输入: ");scanf("%s",input);while(strcmp(input,"我是猪")){printf("输入错误,请输入“我是猪”来取消关机!\n请输入: ");scanf("%s",input);}system("shutdown -c");//取消关机命令return 0;
}

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

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

相关文章

语法和c区别_dockerfile语法

上次写了关于Dockerfile镜像精简之道之后&#xff0c;很多小伙伴找我问&#xff0c;dockerfile语法的一些东西&#xff0c;这边文章就介绍一下dockerfile语法吧FROMFROM是位于我们dockerfile命令的第一层&#xff0c;首先就会使用该命令。当然一个DokcerFile中存在多个镜像时&a…

Dojo学习笔记(三):类化JavaScript

dojo/_base/declare模块是Dojo Toolkit中创建类的基础。declare支持多重继承&#xff0c;这使得开发者能够编写更加灵活的代码并避免代码多次重写。Dojo.Dijit和Dojox模块都使用declare&#xff0c;在这篇文章中&#xff0c;你就知道为什么你也要这样做了。 准备学习 在开始学习…

联想ThinkCentre M8400t-n000等高配电脑重装成xp蓝屏0xc000007b代码

联想ThinkCentre M8400t&#xff0d;n000等高配电脑重装成xp蓝屏0xc000007b代码配置方法&#xff1a;开机进入bios设置界面 &#xff0c;然后把那个硬盘接口从SATA设置成IDE模式。SATA比IDE高级&#xff0c;具有更高的硬盘传输速度&#xff0c;但是早先XP出的时候还不支持SATA&…

Linux进程编程4——父子进程对文件的操作

以下内容源于网络资源的学习与整理&#xff0c;如有侵权请告知删除。 1、子进程继承父进程中打开的文件 &#xff08;1&#xff09;上下文&#xff1a;父进程先用open打开一个文件得到fd&#xff0c;然后再fork创建子进程&#xff0c;之后在父子进程中各自write向fd中写入内容。…

BIOS误删win10引导 delete boot option如何恢复

BIOS误删win10引导 delete boot option如何恢复 其他系统也可以用来参考,解决只是将原来的配置加回去而已 倒了血霉 说个原则,希望大家在发现错误之后第一时间是保护现场不要乱动,如果在百度或别的地方找到了解决方案,先百度一下这个解决方案是否可行,不然不要轻易尝试,这些解决…

fir fpga 不同截止频率_一种新的FIR滤波器系数量化方法

相对于模拟滤波器&#xff0c;数字滤波器具有高精度、高可靠性、可编程改变滤波特性、便于集成等一系列优点&#xff0c;并且理论上可实现近似理想频率特性的滤波性能。经典的数字滤波器主要包括有限脉冲响应(Finite Impulse Response&#xff0c;FIR)滤波器和无限脉冲响应(Inf…

How to: Build a Client Application

转载于&#xff1a;http://msdn.microsoft.com/en-us/library/y6dc64f2(vvs.80).aspx 转载于:https://www.cnblogs.com/aran/archive/2013/02/22/2922438.html

Linux文件和目录权限

前言文件系统权限可以用‘ll’或者‘ls -l’查看第一位表示文件类型&#xff0c;后面9位三三一组分别表示属主&#xff0c;属组&#xff0c;其他用户权限其中r对文件表示可读权限&#xff0c;如cat&#xff0c;tail&#xff0c;more&#xff0c;less等对目录表示可以使用ls命令…

Linux进程编程3——守护进程

以下内容源于网络资源的学习与整理&#xff0c;如有侵权请告知删除。 一、守护进程介绍 1、进程查看命令ps ps -ajx偏向显示各种有关的ID号&#xff1b;ps -aux偏向显示进程各种占用资源 2、&#xff08;用于向进程发送信号的&#xff09;指令kill “kill -信号编号 进程ID”&a…

JSONObject,JSONArray,对象,数组互相转化

json类型对象转化成对象类型 JSONObject.toJavaObject(jsonObj, Object.class)json类型对象转化为List类型 JSONArray.parseArray(JSONObject.toJSONString(object, Object.class))对象转化成String类型的Json数据 JSONObject.toJSONString(object)转载于:https://www.cnblogs.…

pandas用众数填充缺失值_python数据分析包|Pandas-02之缺失值(NA)处理

本篇详解pandas中缺失值&#xff08;Missing data handling&#xff09;处理常用操作。缺失值处理常用于数据分析数据清洗阶段&#xff1b;Pandas中将如下类型定义为缺失值&#xff1a;NaN: ‘’, ‘#N/A’, ‘#N/A N/A’, ‘#NA’, ‘-1.#IND’, ‘-1.#QNAN’,‘-NaN’, ‘-na…

知识点滴:持久层,DAO,API,DAL,BLL,DLL,csproj,sln

知识点滴&#xff1a;持久层&#xff0c;DAO&#xff0c;API&#xff0c;DAL&#xff0c;BLL&#xff0c;DLL&#xff0c;csproj&#xff0c;sln 摘自: http://www.cnblogs.com/niuniu1985/archive/2009/12/10/1620918.html 知识点滴&#xff1a;持久层&#xff0c;DAO&#xf…

系统设计学习

2019独角兽企业重金招聘Python工程师标准>>> 这里原帖地址: http://www.mitbbs.com/article_t/JobHunting/32492515.html 以下为转载内容 我是分割线 稍微总结一下1. 入门级的news feedhttp://www.quora.com/What-are-best-practices-for-building-somethttp://w…

Linux进程编程5——进程间通信(IPC)概述

以下内容源于网络资源的学习与整理&#xff0c;如有侵权请告知删除。 1、为什么需要进程间通信&#xff1f; &#xff08;1&#xff09;进程间通信&#xff08;IPC&#xff09; 指的是2个任意进程之间的通信。&#xff08;2&#xff09;同一个进程在一个地址空间中 同一个进程…

编码 括号_Java编码规范整理汇总

来源&#xff1a;博学谷 作者&#xff1a;照照在Java的入门过程中&#xff0c;我们首先要养成一个良好的编写代码习惯。那么&#xff0c;了解清楚Java的编码规范就显得尤为必要了。编码格式不仅仅是美不美观的问题。这里我们可以试想一下&#xff0c;如果在Java开发中编码不规范…

rabbitmq消息队列,消息发送失败,消息持久化,消费者处理失败相关

转&#xff1a;https://blog.csdn.net/u014373554/article/details/92686063 项目是使用springboot项目开发的&#xff0c;前是代码实现&#xff0c;后面有分析发送消息失败、消息持久化、消费者失败处理方法和发送消息解决方法及手动确认的模式 先引入pom.xml <!--rabbitmq…

人的幸福感取决于什么

1988年4月&#xff0c;霍华德金森24岁&#xff0c;是美国哥伦比亚大学的哲学系博士。他毕业论文的课题是《人的幸福感取决于什么》。为了完成这一课题&#xff0c;他向市民随机派发出了一万份问卷。问卷中&#xff0c;有详细的个人资料登记&#xff0c;还有五个选项&#xff1a…

基于nginx实现缓存功能及uptream模块详细使用方法

基于nginx实现缓存功能及uptream模块详细使用方法一般情况下&#xff0c;前端使用nginx做代理或7层负载并向后实现varish/squid做cache server的效果要好的多nginx与squid做缓存比较nginx比squid有着巨大的优势表现在&#xff1a;nginx是异步假如后端的web服务器&#xff0c;当…

linux中的信号1——进程如何处理信号?

以下内容源于朱有鹏嵌入式课程的学习与整理&#xff0c;如有侵权请告知删除。 一、信号概述 1、信号是内容受限的一种异步通信机制 &#xff08;1&#xff09;信号的目的&#xff1a;用来进程间通信&#xff08;IPC&#xff09;、进程和内核间的通信。 &#xff08;2&#xff…

单片机oled显示浮点数函数_问中文编程在单片机上实现一个电子时钟,总共有几步?...

首先介绍开发一下语言&#xff1a;mcuScript&#xff0c;他是一个支持同时支持中文编程和英文编程的弱数据类型的脚本语言。相关介绍可参考前面的两篇文章:彭贞&#xff1a;mcuScript一个洋名字的中文(汉语)编程语言&#xff0c;初体验​zhuanlan.zhihu.com彭贞&#xff1a;mcu…