【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…...
变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析
一、变量声明设计:let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性,这种设计体现了语言的核心哲学。以下是深度解析: 1.1 设计理念剖析 安全优先原则:默认不可变强制开发者明确声明意图 let x 5; …...
C++:std::is_convertible
C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...

【大模型RAG】Docker 一键部署 Milvus 完整攻略
本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装;只需暴露 19530(gRPC)与 9091(HTTP/WebUI)两个端口,即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...

04-初识css
一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...

C# 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...
在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?
uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件,用于在原生应用中加载 HTML 页面: 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...

Golang——6、指针和结构体
指针和结构体 1、指针1.1、指针地址和指针类型1.2、指针取值1.3、new和make 2、结构体2.1、type关键字的使用2.2、结构体的定义和初始化2.3、结构体方法和接收者2.4、给任意类型添加方法2.5、结构体的匿名字段2.6、嵌套结构体2.7、嵌套匿名结构体2.8、结构体的继承 3、结构体与…...
探索Selenium:自动化测试的神奇钥匙
目录 一、Selenium 是什么1.1 定义与概念1.2 发展历程1.3 功能概述 二、Selenium 工作原理剖析2.1 架构组成2.2 工作流程2.3 通信机制 三、Selenium 的优势3.1 跨浏览器与平台支持3.2 丰富的语言支持3.3 强大的社区支持 四、Selenium 的应用场景4.1 Web 应用自动化测试4.2 数据…...

淘宝扭蛋机小程序系统开发:打造互动性强的购物平台
淘宝扭蛋机小程序系统的开发,旨在打造一个互动性强的购物平台,让用户在购物的同时,能够享受到更多的乐趣和惊喜。 淘宝扭蛋机小程序系统拥有丰富的互动功能。用户可以通过虚拟摇杆操作扭蛋机,实现旋转、抽拉等动作,增…...
【实施指南】Android客户端HTTPS双向认证实施指南
🔐 一、所需准备材料 证书文件(6类核心文件) 类型 格式 作用 Android端要求 CA根证书 .crt/.pem 验证服务器/客户端证书合法性 需预置到Android信任库 服务器证书 .crt 服务器身份证明 客户端需持有以验证服务器 客户端证书 .crt 客户端身份…...