1.入门篇:进程等待函数wait详解
2.wait函数和waitpid的使用和总结
3.要成为一名专业的程序员,从零开始需要怎么一步步来比较好,要把最底层的先学精通吗?(个人认为)求学长
4.system在C语言里是什么意思
入门篇:进程等待函数wait详解
前言:
编程过程中,有时需要让一个进程等待另一个进程,最常见的是父进程等待自己的子进程,或者父进程回收自己的完整的web项目源码子进程资源包括僵尸进程。这里简单介绍一下系统调用函数:wait()。
文章福利小编推荐自己的Linux内核源码交流群:整理了一些个人觉得比较好的学习书籍、视频资料共享在群文件里面,有需要的可以自行添加哦!!!前名可进群领取,并额外赠送一份价值的内核资料包(含视频教程、电子书、实战项目及代码)!
学习直通车: Linux内核源码/内存调优/文件系统/进程管理/设备驱动/网络协议栈
进程等待的作用:
进程等待的方法(如何让父进程进行进程等待):wait函数和waitpid函数
函数原型:
作用:进程一旦调用了wait,就会立刻阻塞自己,由wait分析当前进程中的某个子进程是否已经退出了,如果让它找到这样一个已经变成僵尸进程的子进程,wait会收集这个子进程的信息,并将它彻底销毁后返回;如果没有找到这样一个子进程,wait会一直阻塞直到有一个出现。参数statloc用来保存被收集进程退出时的一些状态,它是crm班课源码一个指向int型的指针。但如果对这个子进程是如何死掉的不在乎,咱们可以将它设置为NULL:pid = wait(NULL);如果成功,wait会返回被收集的子进程的进程ID,如果调用进程没有子进程,调用会失败,wait返回-1,同时errno会被设置为ECHILD。
运行后:
在第二次打印之前有十秒钟的等待时间,这是我们设置的让子进程睡眠的时间,只有子进程睡眠后醒来,它才能正常退出,也就是能被父进程捕捉到。不管设置多长时间,父进程都会等待下去。
注意:
当父进程忘了用wait()函数等待已终止的子进程时,子进程就会进入一种无父进程的状态,此时子进程就是僵尸进程. wait()要与fork()配套出现,如果在使用fork()之前调用wait(),wait()的返回值则为-1,正常情况下wait()的返回值为子进程的PID. 如果先终止父进程,子进程将继续正常进行,只是它将由init进程(PID 1)继承,当子进程终止时,init进程捕获这个状态. 参数status用来保存被收集进程退出时的一些状态,它是一个指向int类型的指针。但如果我们对这个子进程是如何死掉毫不在意,只想把这个僵尸进程消灭掉,(事实上绝大多数情况下,我们都会这样想),我们就可以设定这个参数为NULL,就像下面这样: pid = wait(NULL); 如果成功,wait会返回被收集的钢琴块游戏源码子进程的进程ID,如果调用进程没有子进程,调用就会失败,此时wait返回-1,同时errno被置为ECHILD。 如果参数status的值不是NULL,wait就会把子进程退出时的状态取出并存入其中, 这是一个整数值(int),指出了子进程是正常退出还是被非正常结束的,以及正常结束时的返回值,或被哪一个信号结束的等信息。由于这些信息 被存放在一个整数的不同二进制位中,所以用常规的方法读取会非常麻烦,人们就设计了一套专门的宏(macro)来完成这项工作,下面我们来学习一下其中最常用的两个: 1,WIFEXITED(status) 这个宏用来指出子进程是否为正常退出的,如果是,它会返回一个非零值。 (请注意,虽然名字一样,这里的参数status并不同于wait唯一的参数–指向整数的指针status,而是那个指针所指向的整数,切记不要搞混了。) 2, WEXITSTATUS(status) 当WIFEXITED返回非零值时,spring github源码下载我们可以用这个宏来提取子进程的返回值,如果子进程调用exit(5)退出,WEXITSTATUS(status) 就会返回5;如果子进程调用exit(7),WEXITSTATUS(status)就会返回7。请注意,如果进程不是正常退出的,也就是说, WIFEXITED返回0,这个值就毫无意义。
代码示例:wait.c
运行结果:
wait函数:pid_t wait (int* status)
在编码时有一个代码规范:
如果是输入型,参数定义成引用;
如果是输出或者输入输出参数,参数定义成指针;
wait函数的四个特性:
1.输出型参数,与其对应的有:
2.int* status是一个指针类型占四个字节,但是实际中只使用到后两个字节,将这两个字节分为三部分:
退出码:程序正常退出时用到
coredump标志位,退出信号是程序异常退出时用到:
用退出信号判断进程是否正常退出:
产生coredump文件不能判断进程是否正常退出的原因:
1.判断是否有退出信号
2.判断coredump标志位
3.判断退出码
使用wait函数阻止子进程变成僵尸进程
运行情况:
阻塞:
阻塞概念:当调用结果返回之前,当前的执行流会被挂起,并在得到结果之后返回
父进程一直在wait,并没有返回;
对阻塞和非阻塞理解:
1.子进程一种在运行;
2.子进程已退出
对于两种非阻塞的情况,父进程都是直接退出,但是两种情况父进程退出后,一种正常一种不正常
waitpid函数
wait函数的实现是调用waitpid函数实现
我爱内核网 - 构建全国最权威的内核技术交流分享论坛
原文地址: 进程等待函数wait详解 - 进程管理 - 我爱内核网(侵删)
精彩推荐:
如何理解Linux内核下的进程切换
玩转腾讯首发Linux内核源码《嵌入式开发笔记》,也许能帮到你哦
简要分析Linux下多进程的同步和互斥
[实战篇]红黑树在Linux内核中的应用
%Linux使用者都不知道的内存问题
wait函数和waitpid的使用和总结
当子进程退出时,Linux内核会通过SIGCHLD信号通知父进程。html源码多余换行这种情况下,子进程转变为僵尸状态,仅保留基本数据结构以供父进程查询其退出详情。wait和waitpid函数分别用于处理这种情况。
wait函数的原型是:当调用后,进程会阻塞直到子进程退出,此时会收集子进程信息并销毁,然后返回。status参数可用来存储退出状态,若对详情不感兴趣,可设置为NULL。
waitpid函数则更具体,用于等待指定的进程结束。它支持参数status来获取子进程状态,以及选项如WNOHANG防止阻塞。Linux中可用的选项包括WNOHANG和WUNTRACED,它们可以组合使用。函数成功返回子进程pid,失败则返回-1。
了解这些函数的使用对于监控和管理进程至关重要。如果你对如何更深入地掌握,可以关注博主cs_wu在博客园上的文章,或者尝试c++项目实战课程,包括基础架构、SPDK、内核等技术,以提升专业技能。
有兴趣进一步学习内核技术的朋友,可以加入技术交流群获取资源,如内核源码学习路线和视频教程。点击链接获取更多详情和福利。
要成为一名专业的程序员,从零开始需要怎么一步步来比较好,要把最底层的先学精通吗?(个人认为)求学长
前言
你是否觉得自己从学校毕业的时候只做过小玩具一样的程序?走入职场后哪怕没有什么经验也可以把以下这些课外练习走一遍(朋友的抱怨:学校课程总是从理论出发,作业项目都看不出有什么实际作用,不如从工作中的需求出发)
建议:
不要乱买书,不要乱追新技术新名词,基础的东西经过很长时间积累而且还会在未来至少年通用。
回顾一下历史,看看历史上时间线上技术的发展,你才能明白明天会是什么样。
一定要动手,例子不管多么简单,建议至少自己手敲一遍看看是否理解了里头的细枝末节。
一定要学会思考,思考为什么要这样,而不是那样。还要举一反三地思考。
注:你也许会很奇怪为什么下面的东西很偏Unix/Linux,这是因为我觉得Windows下的编程可能会在未来很没有前途,原因如下:
现在的用户界面几乎被两个东西主宰了,1)Web,2)移动设备iOS或Android。Windows的图形界面不吃香了。
越来越多的企业在用成本低性能高的Linux和各种开源技术来构架其系统,Windows的成本太高了。
微软的东西变得太快了,很不持久,他们完全是在玩弄程序员。详情参见《Windows编程革命史》
所以,我个人认为以后的趋势是前端是Web+移动,后端是Linux+开源。开发这边基本上没Windows什么事。
启蒙入门
1、 学习一门脚本语言,例如Python/Ruby
可以让你摆脱对底层语言的恐惧感,脚本语言可以让你很快开发出能用得上的小程序。实践项目:
处理文本文件,或者csv (关键词 python csv, python open, python sys) 读一个本地文件,逐行处理(例如 word count,或者处理log)
遍历本地文件系统 (sys, os, path),例如写一个程序统计一个目录下所有文件大小并按各种条件排序并保存结果
跟数据库打交道 (python sqlite),写一个小脚本统计数据库里条目数量
学会用各种print之类简单粗暴的方式进行调试
学会用Google (phrase, domain, use reader to follow tech blogs)
为什么要学脚本语言,因为他们实在是太方便了,很多时候我们需要写点小工具或是脚本来帮我们解决问题,你就会发现正规的编程语言太难用了。
2、 用熟一种程序员的编辑器(不是IDE) 和一些基本工具
Vim / Emacs / Notepad++,学会如何配置代码补全,外观,外部命令等。
Source Insight (或 ctag)
使用这些东西不是为了Cool,而是这些编辑器在查看、修改代码/配置文章/日志会更快更有效率。
3、 熟悉Unix/Linux Shell和常见的命令行
如果你用windows,至少学会用虚拟机里的linux, vmware player是免费的,装个Ubuntu吧
一定要少用少用图形界面。
学会使用man来查看帮助
文件系统结构和基本操作 ls/chmod/chown/rm/find/ln/cat/mount/mkdir/tar/gzip …
学会使用一些文本操作命令 sed/awk/grep/tail/less/more …
学会使用一些管理命令 ps/top/lsof/netstat/kill/tcpdump/iptables/dd…
了解/etc目录下的各种配置文章,学会查看/var/log下的系统日志,以及/proc下的系统运行信息
了解正则表达式,使用正则表达式来查找文件。
对于程序员来说Unix/Linux比Windows简单多了。(参看我四年前CSDN的博文《其实Unix很简单》)学会使用Unix/Linux你会发现图形界面在某些时候实在是太难用了,相当地相当地降低工作效率。
4、 学习Web基础(HTML/CSS/JS) + 服务器端技术 (LAMP)
未来必然是Web的世界,学习WEB基础的最佳网站是W3School。
学习HTML基本语法
学习CSS如何选中HTML元素并应用一些基本样式(关键词:box model)
学会用 Firefox + Firebug 或 chrome 查看你觉得很炫的网页结构,并动态修改。
学习使用Javascript操纵HTML元件。理解DOM和动态网页(Dynamic HTML: The Definitive Reference, 3rd Edition - O'Reilly Media) 网上有免费的章节,足够用了。或参看 DOM 。
学会用 Firefox + Firebug 或 chrome 调试Javascript代码(设置断点,查看变量,性能,控制台等)
在一台机器上配置Apache 或 Nginx
学习PHP,让后台PHP和前台HTML进行数据交互,对服务器相应浏览器请求形成初步认识。实现一个表单提交和反显的功能。
把PHP连接本地或者远程数据库 MySQL(MySQL 和 SQL现学现用够了)
跟完一个名校的网络编程课程(例如:mand,想必大家很熟悉shell接受命令之后做的事了。
再解释下fork的原理:当一个进程A调用fork时,系统内核创建一个新的进程B,并将A的内存映像复制到B的进程空间中,因为A和B是一样的,那么他们怎么知道自己是父进程还是子进程呢,看fork的返回值就知道,上面也说了fork在子进程中返回0,在父进程中返回子进程的pid。
windows中的情况也类似,就是execl换了个又臭又长的名字,参数名也换的看了让人发晕的,我在MSDN中找到了原型,给大家看看:
HINSTANCE ShellExecute(
HWND hwnd,
LPCTSTR lpVerb,
LPCTSTR lpFile,
LPCTSTR lpParameters,
LPCTSTR lpDirectory,
INT nShowCmd
);
用法见下:
ShellExecute(NULL, "open", "c:\\a.reg", NULL, NULL, SW_SHOWNORMAL);
你也许会奇怪 ShellExecute中有个用来传递父进程环境变量的参数 lpDirectory,linux中的execl却没有,这是因为execl是编译器的函数(在一定程度上隐藏具体系统实现),在linux中它会接着产生一个linux系统的调用 execve, 原型见下:
int execve(const char * file,const char **argv,const char **envp);
看到这里就会明白为什么system()会接受父进程的环境变量,但是用system改变环境变量后,system一返回主函数还是没变。原因从system的实现可以看到,它是通过产生新进程实现的,从我的分析中可以看到父进程和子进程间没有进程通信,子进程自然改变不了父进程的环境变量。
使用了system函数就能执行dos指令。
#include <stdio.h>
#include <stdlib.h>
xiaoyu()
{
char *a;
int n=0;
FILE *f;
f=fopen("file.bat","w+");/*新建一个批处理*/
if(f==NULL)
exit(1);
a="echo"; /*DOS命令*/
for(n=;n<=;n++)/*大写A-Z*/
fprintf(f,"%s %c\n",a,n);/*利用ASCII码输出A-Z,写出批处理*/
fclose(f);
system("file.bat");/*运行批处理*/
}
main()
{
char *string;
xiaoyu();
string="echo C语言的system函数\n";/*输出中文*/
system(string);
system("pause");/*程序暂停*/
}
C中可以使用DOS命令,以后编程通过调用DOS命令很多操作就简单多了。