自己建设网站需要具备哪些条件创客贴网站建设

pingmian/2026/1/23 5:21:40/文章来源:
自己建设网站需要具备哪些条件,创客贴网站建设,深圳建网站服务商,开发网站五个阶段Linux进程控制(2) #x1f4df;作者主页#xff1a;慢热的陕西人 #x1f334;专栏链接#xff1a;Linux #x1f4e3;欢迎各位大佬#x1f44d;点赞#x1f525;关注#x1f693;收藏#xff0c;#x1f349;留言 本博客主要内容讲解了进程等待收尾内容和进程的程序…Linux进程控制(2) 作者主页慢热的陕西人 专栏链接Linux 欢迎各位大佬点赞关注收藏留言 本博客主要内容讲解了进程等待收尾内容和进程的程序替换以及进程程序替换的原理进程程序替换的7个重要接口 文章目录 Linux进程控制(2)1.进程等待(续)2.进程程序替换2.1 程序替换是如何完成的---单线程版2.2程序替换的原理2.3引入多进程使用所有程序替换的接口熟悉所有的替换程序接口(7个) 1.进程等待(续) 我们稍微改造一下之前进程等待的时候父进程不要阻塞等待的代码让父进程真正的去运行一些任务。 我们采用函数回调的方式让父进程在等待子进程的时候也可以去运行自己的一些任务 #includestdio.h #includestring.h #includeunistd.h #includesys/types.h #includesys/wait.h #includestdlib.h#define TASK_NUM 10//预设一批任务 void sync_disk() {printf(这是一个刷新数据的任务\n); }void sync_log() {printf(这是一个同步日志的任务\n); }void net_send() {printf(这是一个网络发送的任务\n); } //保存相关的任务 typedef void (*func_t)(); //定义了一个函数指针类型 func_t orther_task[TASK_NUM] {NULL}; //装载任务 int Load_Task(func_t fuc) {int i 0;for(; i TASK_NUM; i){if(orther_task[i] NULL) break;}if(TASK_NUM i) return -1;else orther_task[i] fuc;return 0; }//初始化函数指针数组 void Init_Task() {for(int i 0; i TASK_NUM; i) orther_task[i] NULL;Load_Task(sync_disk); Load_Task(sync_log);Load_Task(net_send); }void Run_Task() {for(int i 0; i TASK_NUM; i){if(orther_task[i] NULL) continue;else orther_task[i]();} }int main() {pid_t id fork();if(id 0){//子进程int cnt 5;while(cnt){printf(我是子进程我还活着呢我还有%dS我的pid%d我的ppid%d\n, cnt--, getpid(), getppid());sleep(1);}exit(0);}Init_Task();while(1){int status 0;pid_t ret_id waitpid(id, status, WNOHANG);// 夯住了if(ret_id 0){printf(waitpid_error\n);}else if(ret_id 0){Run_Task(); sleep(1);continue;}else{printf(我是父进程我等待成功了我的pid%d我的ppid%d, ret_id: %d, child exit code: %d, child exit signal:%d\n,getpid(), getppid(), ret_id, (status 8)0xFF, status 0x7F);exit(0);}sleep(1); }return 0; } 运行结果 继续改进我们之前获取进程退出码的时候是使用(status 8) 0xFF的方式来进行获取的那么实际上C库也给我们提供了两个宏来帮助我们获取进程的退出码 status: WIFEXITED(status): 若为正常终止子进程返回的状态则为真。查看进程是否是正常退出 WEXITSTATUS(status): 若WIFEXITED非零提取子进程退出码。查看进程的退出码我们用这两个宏来优化一下我们等待成功也就是子进程结束的时候的代码 else { //等待成功 if(WIFEXITED(status)) { //正常退出 printf(wait success, child exit code :%d, WEXITSTATUS(status)); } else { //异常退出 printf(wait success, child exit signal :%d, status 0x7F); } exit(0); } 正常退出 异常退出我们尝试在父进程等待的时候杀掉子进程 2.进程程序替换 我们为什么需要创建子进程为了让子进程帮我执行特定的任务 ①让子进程执行父进程的一部分代码 ②如果子进程指向一段全新的代码呢这时候我们就需要进程的程序替换 也是为什么需要进程的程序替换。 2.1 程序替换是如何完成的—单线程版 代码 #includestdio.h #includestdlib.h #includeunistd.h int main() { printf(begin......\n); printf(begin......\n); printf(begin......\n); printf(begin......\n); printf(begin......\n); execl(/bin/ls, ls, -a, -l, NULL); printf(end........\n); printf(end........\n); printf(end........\n); printf(end........\n); printf(end........\n); return 0; } 运行结果 那么我们可以看到这个进程运行了开始的begin....,然后运行了ls,但是后面的end...却不见了。 这是因为发生了进程的程序的替换简要的原理就是操作系统通过提供的地址/bin/ls从磁盘中拿出ls然后选到指定的文件ls,在输入一些参数-a, -l以NULL表示结束。 2.2程序替换的原理 操作系统不动当前进程的内核数据结构而是去磁盘内部拿到要替换的数据和代码将我们当前进程的数据和代码替换掉。 当进程调用一种exec函数时,该进程的用户空间代码和数据完全被新程序替换,从新程序的启动例程开始执行。 所以进程的程序替换是没有创建新的进程的。 ①站在进程的角度 操作系统帮我们在磁盘内部找到我们要替换的数据和代码替换进程的数据和代码。 ②站在程序的角度 这个程序被加载了所以我们也称execl这类函数为加载器。 我们在回到一开始为什么我们程序后面的end.....却没有打印出来 原因是当我们加载程序替换的时候新的数据和代码就进入了进程当前进程后续没有没运行的代码就成为了老代码直接被替换了没有机会执行了。 所以进程的程序替换是整体替换而不是局部替换。 所以我们接下来引入多进程的程序替换 2.3引入多进程使用所有程序替换的接口 例程 #includestdio.h #includestdlib.h #includeunistd.h #includesys/types.h #includesys/wait.h int main() { pid_t id fork(); if(id 0) { //child printf(我是子进程%d, getpid()); execl(/bin/ls, ls, -a, -l, NULL); } sleep(2); //father waitpid(id, NULL, 0); printf(我是父进程%d\n, getpid()); return 0; }运行结果 我们看到execl之后父进程的内容也被运行了 因为进程的独立性所以进程的程序替换只会影响调用程序替换的子进程。 子进程加载新程序的时候是需要进行程序替换的发生写时拷贝(子进程执行的可是全新的代码啊新的代码所以代码区也可以发生写时拷贝) 那么对于execl这类加载函数它有没有返回值呢 答案是分情况 ①替换成功是没有返回值的 ②替换失败是有返回值的-1 原因是假设替换替换成功了那么我们该进程中的代码和数据都会被替换成新的代码和数据那么我们之前的返回值也就不复存在了并且我们也不需要返回值了。 替换失败的情况下进程之前的代码和数据还是存在的那么我们的返回值也是存在的从而可以返回。 所以我们调用了加载函数之后我们不用去判断它是否加载成功只需要在函数后面返回异常即可。 失败的例程 #includestdio.h #includestdlib.h #includeunistd.h #includesys/types.h #includesys/wait.h int main() { pid_t id fork(); if(id 0) { //child printf(我是子进程%d\n, getpid()); execl(/bin/lsss, lsss, -a, -l, NULL); exit(1); } sleep(2); //father int status; waitpid(id,status, 0); printf(我是父进程%d, child exit signal:%d\n, getpid(), WEXITSTATUS(status)); return 0; } 熟悉所有的替换程序接口(7个) ①int execl(const char *path, const char *arg, ...); 例如execl(/bin/ls, ls, -a, -l, NULL); l代表list path路径也就是告诉操作系统你要用来替换的程序在磁盘的哪个路径,例程里的/bin/ls arg文件是你要用来替换的文件名例程里面的ls。 其中的...是可变参数列表,例程中的那些参数-a , -l。 其中最后我们要特别的输入一个NULL参数,告诉函数参数结束了 ②int execv(const char *path, char *const argv[]); 相比较第一个函数的差别就是第一个函数要求我们一个一个的去传参数而第二个要求我们直接用数组的形式去传但是原则也是一样的数组的最后一个元素也要置成NULL。 我们在子进程内部调用的时候是这样的 先创建一个数组将这些参数一个一个放进去再传给execv即可 那么其实v就是vector就是数组的意思 char* const argv[] { ls, -a, -l, NULL }; // execl(/bin/lsss, lsss, -a, -l, NULL); execv(/bin/ls, argv); exit(1); } 运行结果 ③int execlp(const char *file, const char *arg, ...); p:当我们指定执行程序的时候只需要指定程序名即可系统会自动在**环境变量PATH**中查找。 也就是说我们要用于替换的程序必须在环境变量PATH中或者说我们在环境变量PATH中设置过 execlp(ls, ls, -a, -l, NULL); 那么其中的两个ls是不一样的一个是文件名一个是参数。 ④int execvp(const char *file, char *const argv[]); v:表示参数以数组的形式传入 p:表示在环境变量PATH中去寻找用于替换的文件 char* const argv[] { ls, -a, -l, NULL }; execvp(ls, argv); 运行结果 ⑤int execle(const char *path, const char *arg, ..., char * const envp[]); envp[]:叫做自定义环境变量当我们不想使用系统默认的环境变量的时候这个时候我们就传递一个envp 比如我们现在要让我们的调用exec目录下的ortherproc来替换myproc的子进程的后续代码 先用execl尝试一下 execl(./exec/ortherproc, ortherproc, NULL); 运行结果 换成的动态的效果再看看 下来我们尝试用execle来实现一下 proc.c char* const envp[] { MYENVPUCanCMe!, NULL }; execle(./exec/ortherproc, ortherproc,envp); ortherproc.cc for(int i 0; i 5; i) { cout 我是另一个程序我的PID是 getpid() endl; cout MYENVP: (getenv(MYENVP)NULL ? NULL : getenv(MYENVP)) endl; cout PATH: (getenv(PATH) NULL ? NULL : getenv(PATH)) endl; sleep(1); } 运行结果 我们看到自定环境变量打印出来了但是操作系统内部的环境变量却不见了所以我们可以得到一个结论 自定义环境变量覆盖了默认的环境变量 我们传默认的环境变量试试 extern char ** environ;execle(./exec/ortherproc, ortherproc,NULL , environ); 运行结果 那么如果我们两个都要呢那么有一个接口putenv给我们提供了一个将自定义环境变量追加到进程的默认环境变量的方法接下来我们尝试一下 putenv(MYENVPUCanCMe); execle(./exec/ortherproc, ortherproc, NULL, environ); 运行结果 插播一段 我们知道环境变量具有全局属性可以被子进程继承下去那么操作系统是怎么办到的 只需要用execle的最后一个参数传过去即可 那么我们是不是不需要putenv也能实现两个都能被子进程读取到呢 我们直接把自定义的环境变量export到bash中试试 [milavm-5wklnbmaja lesson6]$ export MYENVPUCanCMe [milavm-5wklnbmaja lesson6]$ echo $MYENVP UCanCMe运行结果 我们发现是可行的自定义环境变量----- bash -----父进程------子进程 ⑥int execvpe(const char *file, char *const argv[], char *const envp[]); p不需要指定路径只要在环境变量内部即可 v参数以数组的形式传入 e环境变量数组传入 使用方法都与上面的类似。 ⑦int execve(const char *filename, char *const argv[], char *const envp[]); 这个接口也不用过多介绍了使用方法都是一样的。 那么我们需要注意的是在linux的man手册中将区域六个接口都放在了3号手册唯独这个却放在了2号手册。 其实操作系统只给我们提供了一个程序替换的接口execve,剩下的几个接口都是由这个接口封装出来的。 并且我们程序替换的时候不仅可以替换C语言的甚至其他的语言都可以替换我上面的例子也做到了用C替换因为这些代码都是交给操作系统来处理的而不是编译器所以不论是什么语言都是可以替换的 到这本篇博客的内容就到此结束了。 如果觉得本篇博客内容对你有所帮助的话可以点赞收藏顺便关注一下 如果文章内容有错误欢迎在评论区指正

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

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

相关文章

那些网站做任务领q币东莞公司网站价格

C语言中如何使用宏C(和C)中的宏(Macro)属于编译器预处理的范畴,属于编译期概念(而非运行期概念)。下面对常遇到的宏的使用问题做了简单总结。 关于#和## 在C语言的宏中,#的功能是将其…

天津做淘宝网站教务系统登录入口

下列代码都是以自己的项目实例讲述的,相关的文本内容很少,主要说明全在代码注释中。我是使用阿里云云通信的短信服务,第一次使用会摸不着头绪,这里我们需要做些准备工作:1、登陆自己的账号进入阿里云官网,没…

深圳做微信网站制作成都有哪些做网站开发的大公司

if __name__ __main__: 是一个常见的 Python 代码块,通常作为程序的主入口。 这个代码块通常用于包含脚本的主要功能或逻辑,它会在脚本被直接执行时运行,但不会在脚本作为模块导入时运行。 其中,__name__ 是 Python 中的一个特…

潍坊专业网站建设价格低专业的天津网站建设

前端问题合集:VueElementUI 1. Vue引用Element-UI时,组件无效果解决方案 前提: 已经安装好elementUI依赖 //安装依赖 npm install element-ui //main.js中导入依赖并在全局中使用 import ElementUI from element-ui Vue.use(ElementUI)如果此…

wordpress 不能换主题东莞网站优化教程

『Postman入门万字长文』| 从工具简介、环境部署、脚本应用、Collections使用到接口自动化测试详细过程 1 Postman工具简介2 Postman安装3 Postman界面说明4 一个简单请求4.1 请求示例4.2 请求过程 5 Postman其他操作5.1 import5.2 History5.3 Environment5.4 Global5.5 其他变…

免费网站的软件网站开发任务需求书

Mysql 数据库是所有软件体系中最核心的存在 DBA 1.1什么是数据库 数据库(DB,DataBase) 概念:数据仓库,软件,安装在操作系统上(window,linux...) 作用:存…

十大中国网站制作门户网站英文

文章目录一、 编辑配置文件1.1. 进入tomcat的conf目录1.2. 编辑tomcat-users.xml文件1.3. 添加配置信息二、 配置说明三、 启动tomcat服务3.1. 启动tomcat3.2. 浏览器访问3.3. 点击Manager App访问4033.4. 编辑配置文件3.5. 注释value部分3.6. 浏览器再次请求四、新建任务&…

网上做论文的网站软件工程师是做什么的

一.DDT简介 Data Driven Testing,数据驱动,简单来说就是测试数据的参数化 Python数据驱动模块DDT,包含类的装饰器ddt和两个方法装饰器data(直接输入测试数据) 通常情况下,data中的数据按照一个参数传递给…

什么情况下需要建设网站安卓手机网页视频怎么下载

多线程中,锁用于确保同一时间只有一个线程可以访问共享资源,从而避免并发访问导致的数据不一致或者竞争条件等问题。 常见的锁有两种:互斥锁和读写锁。互斥锁的作用是保护共享资源,同时只允许一个线程访问,其他线程需…

店铺外卖网站怎么做wordpress网站源码分享

目录 一、协同过滤(Collaborative Filtering, CF)1. 基于用户的协同过滤2. 基于物品的协同过滤 二、深度学习在推荐系统中的应用1. 深度学习模型的优势2. 深度学习在推荐系统中的应用实例 三、总结与展望 推荐系统是现代信息处理和传播中不可或缺的技术&…

精品课程网站的建设初中做网站的软件

文章目录 从零开始学Go web——第一天一、Go与web应用简介1.1 Go的可扩展性1.2 Go的模块化1.3 Go的可维护1.4 Go的高性能 二、web应用2.1 工作原理2.2 各个组成部分2.2.1 处理器2.2.2 模板引擎 三、HTTP简介四、HTTP请求4.1 请求的文本数据4.2 请求方法4.2.1 请求方法类型4.2.2…

盐步网站制作开网页慢

陆家建伟国际汽车城,均价 7500 元/㎡美吉特家居广场,均价 17000 元/㎡美吉特灯都,均价 17000 元/㎡花桥绿地象屿苏河公园,均价 22950 元/㎡凯德都会新峰,均价 21500 元/㎡越洋国际,均价 18000 元/㎡浦西玫瑰…

深圳网站建设定制开发服务简洁的企业网站

个人主页:仍有未知等待探索-CSDN博客 专题分栏:C_仍有未知等待探索的博客-CSDN博客 目录 一、C关键字 二、命名空间 1、区别 1. C语言 ​编辑 2. C 2、命名空间定义 3、命名空间的使用 三、C输入&输出 四、缺省参数 五、函数重载 六、引用 …

旅游管理网站业务模块东莞关键词自动排名

Intellij 的Java/安卓工具链有着一种不可持续性,这种不可持续性体现在多个方面。 首先是不可持续运行。IDEA 使用时间越长,内存占用越大,从不主动释放。运行时间越长,日志越多,从不主动清理。 然后是不完整的开源&am…

云南建设网站首页视频网站如何做弹幕

• 高性能 XBurst 1 CPU,主频1.0GHz • 超低功耗 • 内置LPDDR2(X1600:32MB,X1600E:64MB) • 实时控制核XBurst 0,面向安全管理和实时控制 • 丰富的外设接口 应用领域 • 基于二维码的智能商业 • 智能物联网 • 高端…

wordpress 网站的占有wordpress下载验证码

近日,艾瑞咨询发布《2023年中国保险业数字化转型研究报告》,摩斯隐私计算解决方案被报告入选,并获得“保险业数字化卓越服务商”奖。 蚂蚁摩斯是隐私计算行业的领先布局者:早在2017年,蚂蚁集团启动了隐私计算项目&…

爱企业 查询怎么来自己做网站优化

视频哈工大李治军老师:https://www.bilibili.com/video/BV1d4411v7u7?p12 参考文档:https://blog.csdn.net/SakuraA6/article/details/108810916 学长在我大一推荐我看,p12和p13的内容真的有那么难吗,现在已经是我看的第三遍了还…

专业做甜点的网站手套外包加工网

aconda 是做什么用的这里就不说了,一般玩Python的都知道这东西,最早接触这东西是因为它把NVIDIA中cuda计算和Python互连的一个库拿下了,是买下来了还是专业,还是唯一合作的也就记不清了,那就是 numba , 那些年头Python…

微网站建设报价方案专业的制作网站开发公司

题目 给你两个单词 w o r d 1 word1 word1 和 w o r d 2 word2 word2, 请返回将 w o r d 1 word1 word1 转换成 w o r d 2 word2 word2 所使用的最少操作数 。 你可以对一个单词进行如下三种操作: 插入一个字符删除一个字符替换一个字符 方法—动…

做360网站中保存的图片存在哪里的红尘直播

一.有两角夹一边分别相等的两个三角形全等 数学证明: 设△ A B C 与△ A 1 B 1 C 1 ∠ B ∠ B 1 , ∠ C ∠ C 1 , B 1 C 1 B C 设△ABC与△A_1B_1C_1∠B∠B_1,∠C∠C_1,B_1C_1BC 设△ABC与△A1​B1​C1​∠B∠B1​,∠C∠C1​,B1​C1​BC ①移动 ∠ B 1 与 ∠ B 重合 , 边 B…