【Linux】进程exec函数族以及守护进程
一.exec函数族
1.exec函数族的应用
在shell下敲shell的命令都是在创建shell的子进程。而我们之前学的创建父进程和子进程代码内容以及通过pid与0的关系来让父子进程执行不同的代码内容都是在一个代码文件里面,而shell是如何做到不在一个文件里面写代码使之成为子进程的呢?
答案是使用了exec函数族
假如现在有段在shell下敲的名为test的代码,执行过程为:父进程(shell)fork()出一个子进程后,子进程调用exec函数族执行test,此时原进程的内容就会被覆盖,执行test的内容,就实现了创建新的进程并在该进程中执行不同的程序;
这些函数允许将当前进程内容替换为新的可执行文件,从而实现进程的代码和数据的切换。
进程调用exec函数族执行某个程序
进程当前内容被指定的程序替换
实现让父子进程执行不同的程序 :
●父进程创建子进程
●子进程调用exec函数族
●父进程不受影响
2.exec函数族的一些常见成员
(1)excel / excelp(熟练)
#include <unistd.h> int execl(const char *path, const char *arg, …); int execlp(const char *file, const char *arg, …);成功时执行指定的程序;失败时返回EOF
path 执行的程序名称,包含路径
arg… 传递给执行的程序的参数列表
file 执行的程序的名称,在PATH中查找(PATH为linux的环境变量,添加到系统的环境变量后,在系统的任意路径都能直接输入程序名称执行,不用输入路径)
execl : 以参数列表的方式执行新程序。需要指定可执行文件的路径,以及传递给新程序的参数列表。
进程创建 – execl(p) – 示例:
⭕ 执行ls命令,显示/etc目录下所有文件的详细信息
#include <stdio.h>
#include <unistd.h>int main(int argc, const char *argv[])
{if(execl("/bin/ls","ls","-a","-l","/etc",NULL)<0){perror("execl");}return 0;
}
#include <stdio.h>
#include <unistd.h>int main(int argc, const char *argv[])
{if(execlp("ls","ls","-a","-l","/etc",NULL)<0){perror("execl");}return 0;
}
分析:
execl中:
"/bin/ls"为执行的程序名称,在/bin路径下有个叫ls的程序;
"ls"是第0个参数,第0个参数通常是程序的名称,第0个参数必须要写,虽然它没有使用;
"-a","-l","/etc"都是传递给程序的参数;
execlp中:除了直接传入程序名称在系统路径中查找以外,其余和execl相同;
注意:两个函数区别在于execlp不需要写文件名全路径,在系统路径PATH查找
最后一个参数都必须用空指针(NULL)作结束
进程当前内容被指定的程序替换,但进程号不变
第0个参数必须要写,虽然它没有使用
(2)execv / execvp (熟练)
#include <unistd.h>int execv(const char *path, char *const argv[]);int execvp(const char *file, char *const argv[]);成功时执行指定的程序;失败时返回EOF ;
arg… 封装成指针数组的形式;
这两个就是把参数列表封装成了一个数组;
进程创建 – execv(p) – 示例
⭕执行ls命令,显示/etc目录下所有文件的详细信息
伪代码如下:
char *arg[] = {“ls”, “-a”, “-l”, “/etc”, NULL};if (execv(“/bin/ls”, arg) < 0){perror(“execv”);} if (execvp(“ls”, arg) < 0){perror(“execvp”);}
注意:末尾的NULL照样不能省;
3.system(exec的简略版本) (熟练)
内部使用了 exec 函数族的一种方式来执行 shell 命令
#include <stdlib.h> int system(const char *command);成功时返回命令command的返回值;失败时返回EOF
当前进程
system函数会创建一个子进程来执行 shell 命令,等待执行结束后才继续执行
system函数一般用来执行shell命令,并不适用于直接执行可执行程序,一般使用exec函数族来执行可执行程序。
#include <stdlib.h>int main(int argc, const char *argv[])
{system("/bin/ls -a -l /etc");return 0;
}
二.守护进程
1.守护进程的特点(了解)
(1)守护进程
守护进程(Daemon Process)是Linux三种进程类型之一;
是 Linux 中的后台服务进程;
是一个生存期较长的进程,通常独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件;
(2)守护进程特点
始终在后台运行
独立于任何终端
周期性的执行某种任务或等待处理特定事件
它是个特殊的孤儿进程,这种进程脱离终端,为什么要脱离终端呢?之所以脱离于终端是为了避免进程被任何终端所产生的信息所打断,其在执行过程中的信息也不在任何终端上显示。由于在 Linux 中,每一个系统与用户进行交流的界面称为终端,每一个从此终端开始运行的进程都会依附于这个终端,这个终端就称为这些进程的控制终端,当控制终端被关闭时,相应的进程都会自动关闭
举例:
http 服务的守护进程叫 httpd,mysql 服务的守护进程叫 mysqld。
2.会话、控制终端(了解)
进程组(Process Group): 进程集合,每个进程组有一个组长(Leader),其进程 ID 就是该进程组 ID。
会话(Session): 进程组集合,每个会话有一个组长,其进程 ID 就是该会话组 ID。
控制终端(Controlling Terminal):每个会话可以有一个单独的控制终端,与控制终端连接的 Leader 就是控制进程(Controlling Process)。
即进程的集合为进程组,进程组集合为会话组 ,会话组的控制终端为控制进程;

3.创建守护进程流程(熟练)
简便地创建守护进程: nohup 命令
nohup xxxx &
nohup在某些情况下是方便的,但是需要创建更稳定和更高级需求的守护进程时并不推荐nohup;
接下来我们介绍学习另外的方法:
(1)创建子进程,父进程退出
if (fork() > 0)
{exit(0);
}
子进程变成孤儿进程,被init进程收养
子进程在后台运行
(2)子进程创建新会话
setsid函数:
#include <unistd.h>pid_t setsid(void);成功:返回调用进程的会话ID;失败:-1,设置errno。
作用:用于创建一个新的会话,并将调用进程设置为这个新会话的领导进程(session leader),同时也是一个新进程组的组长。这使得进程完全脱离原始的控制终端,而且它的子进程将成为这个新会话和进程组的成员
调用了setsid函数的进程,既是新的会长,也是新的组长;
if(setsid()<0)
{perror("setsid:");exit(-1);
}
此时
子进程成为新的会话组长
子进程脱离原先的终端
(3)更改当前工作目录
守护进程一直在后台运行,其工作目录不能被卸载要具有稳定性,因此最好重新设定一个稳定的工作目录;
chdir("/");
chdir("/tmp");
(4)重设文件权限掩码
umask()是一个用于设置文件创建权限掩码的系统调用函数。当进程创建新文件或目录时,会根据当前的文件创建权限掩码来确定新文件的权限;
if(umask(0)<0)
{exit(-1);
}
文件权限掩码设置为0;
只影响当前进程创建的新文件的权限;
(5)关闭打开的文件描述符
在脱离终端控制后,stdin / stdout / stderr无法再使用,所以需要把这三个的文件描述符关闭,标准输入(0)、标准输出(1)、和标准错误(2)
int i;
for(i=0; i<3; i++)
{close(i);
}
关闭所有从父进程继承的打开文件
已脱离终端,stdin / stdout / stderr无法再使用
(6)步骤总结
第一步:用exit()将父进程退出,使子进程成为孤儿进程被init进程收养;
第二步:子进程利用setsid()函数创建新的会话,脱离原来的终端,成为会话组长;
第三步:使用chdir()更改工作的目录;
第四步:使用umask()重设文件权限掩码;
第五步:关闭文件描述符。
第一步可用nohup xxx & 命令进行,但是不推荐;
第一二步是必须完成的,后面是根据自己的实际情况进行的。
4.守护进程—示例
创建守护进程,每隔1秒将系统时间写入文件time.log
#include <stdio.h>
#include <unistd.h>
#include <time.h>
#include <stdlib.h>int main(int argc, const char *argv[])
{pid_t pid;FILE *fp;time_t t;int i;if((pid = fork())<0){perror("fork");exit(-1);}else if(pid>0){exit(0);}setsid();umask(0);chdir("/tmp");close(0);close(1);close(2);if((fp = fopen("time.log","a")) == NULL){perror("fopen");exit(-1);}while(1){time(&t);fprintf(fp,"%s\n",ctime(&t));fflush(fp);sleep(1);}return 0;
}相关文章:
【Linux】进程exec函数族以及守护进程
一.exec函数族 1.exec函数族的应用 在shell下敲shell的命令都是在创建shell的子进程。而我们之前学的创建父进程和子进程代码内容以及通过pid与0的关系来让父子进程执行不同的代码内容都是在一个代码文件里面,而shell是如何做到不在一个文件里面写代码使之成为子进…...
为什么 ChatGPT 不火了?
不火了是有原因的,下面我来从大部分人拿到 ChatGPT 之后的两大痛点开始讲起: 很多朋友拿到 ChatGPT 后的第一个痛点就是:用的不好 你经常会感觉到 ChatGPT 回答的好空,没有太多参考价值。 而第二个痛点则是:无处去用…...
Ubuntu22.04下安装kafka_2.11-0.10.1.0并运行简单实例
目录 一、版本信息 二、安装Kafka 1.将Kafka安装包移到下载目录中 2.下载Spark并确保hadoop用户对Spark目录有操作权限 三、启动Kafka并测试Kafka是否正常工作 1.启动Kafka 2.测试Kafka是否正常工作 一、版本信息 虚拟机产品:VMware Workstation 17 Pro 虚…...
【S32K3 MCAL配置】-7.2-GPT Driver:仿OS,周期/定时调用APP SWC和BSW模块的主函数
"><--返回「Autosar_MCAL高阶配置」专栏主页--> 案例背景:当没有移至FreeRTOS时,如何仿OS,快速搭建“若干个周期执行的Task”,在其中周期/定时调用APP SWC和BSW模块的主函数。 并在这个简易的仿OS中,如何设置“主函数调用的先后顺序”,以及如何设置“主函…...
golang内置包里面的sort.Slice 切片排序函数使用示例
go语言里面用的最多的数据类型应该是切片Slice了, 今天就给大家介绍这个go内置包里面的切片排序函数的使用方法 函数原型 func Slice(x any, less func(i, j int) bool) 参数说明 这个函数有2个参数, 第一个是你要进行排序的slice切片,地个…...
Golang | Leetcode Golang题解之第70题爬楼梯
题目: 题解: func climbStairs(n int) int {sqrt5 : math.Sqrt(5)pow1 : math.Pow((1sqrt5)/2, float64(n1))pow2 : math.Pow((1-sqrt5)/2, float64(n1))return int(math.Round((pow1 - pow2) / sqrt5)) }...
区块链 | NFT 相关论文:Preventing Content Cloning in NFT Collections(三)
🐶原文: Preventing Content Cloning in NFT Collections 🐶写在前面: 这是一篇 2023 年的 CCF-C 类,本博客只记录其中提出的方法。 F C o l l N F T \mathbf{F_{CollNFT}} FCollNFT and Blockchains with Native S…...
Unity技术学习:渲染大量物体的解决方案,外加RenderMesh、RenderMeshInstanced、RenderMeshIndirect的简单使用
叠甲:本人比较菜,如果哪里不对或者有认知不到的地方,欢迎锐评(不玻璃心)! 导师留了个任务,渲染大量的、移动的物体。 寻找解决方案: 当时找了几个解决方案: 静态批处…...
[数据概念|方案实操][最新]数据资产入表4月速递
“ 在各地数据资产变现“热辣滚烫”” 国家数据局全国数据工作会议前后,数据资源“入表”的尝试在各地持续热火朝天地展开,多地实现数据资产入表和利用数据资产进行融资实现“零的突破”。 我们今天就把4月前后的案例做一个小结,之前的案例大…...
C++中使用Multimap和Vector管理和展示数据
一: 在本文中,我们将探讨如何在C中使用vector和multimap容器来管理一个简单的员工数据系统。我们将创建一个员工类,随机生成员工数据,将员工分组,并展示各组员工的详细信息。此示例展示了C标准模板库(STL&…...
Java---类和方法的再学习
上一篇主要介绍了面向对象的思想以及内存实现,关于类与对象感觉写的不够好,因此才会有这一篇作为补充; 一:类与对象 (1)类 一些相同属性和行为的事物的统称,比较广泛、抽象,比如…...
C语言每日一练(12、水仙花数)
在编程的领域中,我们常常会遇到一些有趣而富有挑战性的问题。今天,让我们一起来探讨一个经典的编程题目——打印出所有的“水仙花数”。 所谓“水仙花数”,是指一个三位数,其各位数字的立方和等于该数本身。例如,153 …...
HTML5实现酷炫个人产品推广、工具推广、信息推广、个人主页、个人介绍、酷炫官网、门户网站模板源码
文章目录 1.设计来源1.1 主界面1.2 我的产品界面1.3 关于我们界面1.4 照片墙界面1.5 发展历程界面1.6 优秀人才界面1.7 热门产品界面1.8 联系我们界面 2.灵活调整模块3.效果和源码3.1 动态效果3.2 源代码 源码下载 作者:xcLeigh 文章地址:https://blog.c…...
系统如何做好安全加固?
一、Windows系统 Windows系统出厂时,微软为了兼容性,默认并未对系统安全做严格的限制,因此还需要做一些基本的安全加固,方可防止黑客入侵。 1、系统补丁更新 为什么要更新系统补丁?很多人感觉漏洞更新没必要&#x…...
对NI系统和PLC系统的应用比较
以下是对这两种系统的基本比较: 1. 设计和功能性 NI系统: 通常基于LabVIEW等软件平台,提供强大的数据采集、信号处理和图形界面开发能力。高度模块化和可扩展,支持各种传感器和信号类型。适合进行复杂的数据分析和高级控制算法的…...
微服务架构中的挑战及应对方式:Outbox 模式
使用 Outbox 模式保持微服务数据一致性 在一个由许多小型服务组成的系统中保持数据一致性是困难的,因为它们分散在各处。以下是一些常见问题以及如何处理它们的方法:当服务发送消息时,同时更新数据库和发送消息是棘手的问题。 在微服务中发出…...
使用Docker安装MySQL5.7.36
拉取镜像并查看 docker pull mysql:5.7.36拉取成功后查看(非必须) docker images创建并设置宿主机 mysql 配置文件目录和数据文件目录 创建相关文件夹将容器中的mysql数据保存到本地,这样即使容器被删除,数据也不会丢失。 mkd…...
【PyTorch】6-可视化(网络结构可视化、CNN可视化、TensorBoard、wandb)
PyTorch:6-可视化 注:所有资料来源且归属于thorough-pytorch(https://datawhalechina.github.io/thorough-pytorch/),下文仅为学习记录 6.1:可视化网络结构 Keras中可以调用model.summary()的API进行模型参数可视化 torchinfo…...
C++容器——map和pair对组
pair(对组) 是一种模板类,允许将两个不同类型的值组合在一起。它由两个数据成员first和second组成,分别用来保存这两个值。 头文件 加头文件 #include<utility> 对于 C11 及以上标准,pair 类型可以在不包含头…...
MVC和DDD的贫血和充血模型对比
文章目录 架构区别MVC三层架构DDD四层架构 贫血模型代码示例 充血模型代码示例 架构区别 MVC三层架构 MVC三层架构是软件工程中的一种设计模式,它将软件系统分为 模型(Model)、视图(View)和控制器(Contro…...
Meixiong Niannian与SpringBoot微服务架构
Meixiong Niannian与SpringBoot微服务架构 1. 引言 在当今快速发展的AI应用领域,如何将强大的画图引擎无缝集成到企业级系统中是一个关键挑战。Meixiong Niannian作为一款高性能的AI画图引擎,能够生成高质量的图像内容,而SpringBoot微服务架…...
A-59F 多功能语音处理模组:覆盖全场景人群,让每一次语音都清晰无噪
在门禁对讲、会议扩音、车载通话、导游喊话、监护设备、智能工牌等各类语音设备中,啸叫刺耳、环境嘈杂、回音不断、拾音模糊、通话断续是所有人共同的痛点。一款真正解决问题的核心硬件 ——A-59F 多功能语音处理模组,它集成扩音防啸叫、AI ENC 降噪、AE…...
告别复杂配置:SDXL 1.0电影级绘图工坊开箱即用体验
告别复杂配置:SDXL 1.0电影级绘图工坊开箱即用体验 1. 为什么选择SDXL 1.0电影级绘图工坊 在AI绘图领域,Stable Diffusion XL(SDXL)1.0代表了当前最先进的文本到图像生成技术。然而,对于大多数非技术背景的创作者来说…...
OpenClaw与nanobot镜像结合:打造个人AI研究助手全流程
OpenClaw与nanobot镜像结合:打造个人AI研究助手全流程 1. 为什么需要个人AI研究助手? 作为一名经常需要阅读大量论文的研究者,我发现自己每天要重复处理许多机械性工作:在多个学术平台检索最新文献、下载PDF并分类存储、提取关键…...
CSMA/CA协议NAV计算实战:用C语言模拟802.11无线网络时序(附完整代码)
CSMA/CA协议NAV计算实战:用C语言模拟802.11无线网络时序(附完整代码) 在无线网络通信领域,CSMA/CA协议是确保数据传输可靠性的基石。不同于有线网络中的CSMA/CD协议,CSMA/CA通过独特的冲突避免机制解决了无线环境中的隐…...
JPEXS Free Flash Decompiler社区大使选拔流程:申请与评审完全指南
JPEXS Free Flash Decompiler社区大使选拔流程:申请与评审完全指南 【免费下载链接】jpexs-decompiler JPEXS Free Flash Decompiler 项目地址: https://gitcode.com/gh_mirrors/jp/jpexs-decompiler JPEXS Free Flash Decompiler是一款功能强大的Flash反编译…...
BootstrapBlazor滑块组件:如何实现垂直方向滑动控制
BootstrapBlazor滑块组件:如何实现垂直方向滑动控制 【免费下载链接】BootstrapBlazor 项目地址: https://gitcode.com/gh_mirrors/bo/BootstrapBlazor BootstrapBlazor滑块组件为Blazor开发者提供了强大的数值输入控件,而垂直方向滑块则是构建现…...
CPU工作原理:从二进制加法器到计算系统
CPU工作原理:从二进制加法器到计算系统的演进 1. 计算需求与二进制表示 在数字计算领域,加法是最基础也是最重要的运算之一。让我们从一个简单的数学问题开始:6324 244675 ?这个看似简单的加法问题,揭示了计算系统的…...
【VASP脚本进阶】Perl脚本解析:Materials Studio原子约束信息如何精准写入POSCAR
1. Perl脚本在VASP计算中的关键作用 做材料模拟的朋友们肯定都遇到过这样的场景:在Materials Studio里精心搭建好模型,设置完原子约束,结果导出到VASP时发现固定原子的信息全丢了。这种时候,一个靠谱的Perl脚本简直就是救命稻草。…...
大数据毕业设计 hadoop+spark+kafka+hive动漫推荐系统 动漫数据分析 可视化 漫画推荐
1、项目介绍 技术栈: Python语言、Django框架、SQLite数据库、Echarts可视化 、HTML、基于物品协同过滤推荐算法 (1)首页------不同类 型的动漫数据 (2)动漫类型饼图 (3)动漫收藏排名和不同国家…...
