第四节 Linux 进程复制与替换
1、printf 函数输出问题printf 函数并不会直接将数据输出到屏幕而是先放到缓冲区中。只有一下三种情况满足才会输出到屏幕① 缓冲区满 ②强制刷新缓冲区 fflush强制刷新到文件中 ③程序结束时。exit()调用exit结束当前进程stdout输入在屏幕上和stdin相对会执行用户态的资源清理操作在调用内核级别的进程终止逻辑执行步骤①执行用户注册的“退出处理函数”②.刷新并关闭标准I/O流把缓冲内容强制刷新到终端或文件中③清理进程私有的资源④.调用_exit()触发内核回收。_exit()结束进程跳过用户操作但是会将缓冲区的内容清空Unix系统调用,不会打印在屏幕上。_exit直接触发内核回收会跳过所有用户的用户态操作直接通知内核终止进程。①.不执行退出处理函数②不执行标准I/O缓冲区用法①.普通单进程程序优先使用exit()②.多进程程序父/子进程子进程优先使用_exit()避免干扰父进程的用户的用户资源父进程使用exit.exit_exit函数类型C标准函数系统调用从man里面可以体现标准I/O缓冲区强制刷新并关闭不刷新直接丢弃数据2、主函数参数介绍int main( int argc, char* argv[], char* envp[])(1) argc 参数个数(2) argv 参数内容(3) envp 环境变量测试一解释argc argument count参数计数器程序自身文件名永远算第 1 个参数不带参数运行时argc1argv argument vector参数字符串数组char* argv[]是字符串数组每个元素存一个命令行参数测试二注意envpenvironment pointer系统环境变量字符串数组。envp 关键特性数组中每一条格式变量名变量值例如SHELL/bin/bash数组末尾用NULL标记结束所以循环条件写envp[i]!NULL环境变量由操作系统 / Shell 提供记录系统配置、终端、桌面、路径等全局信息。3、复制进程 forkpid_t fork(void)函数返回类型 pid_t 实质是 int 类型头文件:unistd.h返回的是整数类型有三种返回情况①.在父进程中返回子进程的PID正整数0用于父进程的识别和子进程的管理②.在子进程中PID的返回值是0,用于确认子进程的身份③.如果是-1表示fork失败内存不足系统进程数达到上限设置错误原因给到系统全局变量errno表示错误原因。测试一#includestdio.h #includestdlib.h #includestring.h #includeunistd.h #include sys/types.h int main() { int n0; char*sNULL; pid_t pidfork(); if((-1)pid)//fork失败内存不足系统进程数达到上限 { printf(false\n); exit(1); } else if(0pid) {//子进程 schild; n3; } else {//父进程 sparent; n7; } for(int i0;in;i) { printf(%s\n,s); sleep(1); } }注意此代码fork()调用完成后父子两个进程同时进入就绪队列子进程运行结束后会变成僵尸进程父进程不会自动回收子进程资源若需要解决僵尸进程需要在父进程代码末尾添加wait(NULL);等待子进程退出并回收资源。fork()练习测试1#includestdio.h #includestdlib.h #includeunistd.h #includestring.h int main(int argc, char *argv[], char *envp[]) { int i 0; for( ; i 2; i ) { fork(); printf(A\n); } exit(0); }测试2#includestdio.h #includestdlib.h #includeunistd.h #includestring.h int main(int argc, char* argv[],char* envp[]) { int i 0; for( ; i 2; i ) { fork(); printf(A); } exit(0); }测试3#includestdio.h #includestdlib.h #includestring.h #includeunistd.h int main(){ fork() || fork(); printf(A\n); exit(0); }测试4#includestdio.h #includestdlib.h #includestring.h #includeunistd.h int main(){ fork() || fork(); printf(A); _exit(0); }测试5注意\n#includestdio.h #includestdlib.h #includestring.h #includeunistd.h int main(){ fork() || fork(); printf(A\n); _exit(0); }测试6#includestdio.h #includestdlib.h #includestring.h #includeunistd.h int main(){ for(int i0;i2;i) fork(); printf(A); }测试7fork()出来的子进程会继承父进程缓冲区中的内容注意有什么疑问或者内容有什么不合理需要修改可以发在评论区我会及时回复感谢大家