[linux c] fork 等函数编写执行命令实验

简介:

相关知识点

一、exit程序退出

    exit(0);表示 非正常结束程序
    exit(0);表示在正常下结束程序 

    exit(1);表示强制结束程序 

    _exit()终止程序时,不关闭任何文件,不清除任何缓冲器,也不调用任何终止函数   
     abort()程序终止运行,不清除文件,返回到调用过程,一般用在防止程序失控,

二、fork

fork会自己创建一个内存空间,复制 父进程的内存空间内容到这个内存空间

vfork 则是共享父进程的内存空间(共享数据段)


实验过程

实验一

使用 fork、exit 和 exec 系统调用编写多进程程序
1.fork

#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
int global=22;
char buf[]="the test content!\n";
int main(void)
{
int test=0,stat;
pid_t pid;
if(write(STDOUT_FILENO, buf, sizeof(buf)) != sizeof(buf))
{ perror("write error!"); }
printf(" fork test!\n");
/* fork */
pid = fork();
 /*we should check the error*/
if (pid == -1)
{
perror("fork");
exit(0);
}
else if (pid == 0)
{
global++;
 test++;
printf("global=%d test=%d Child,my PID is %d\n",global,test,getpid());
exit(0);
}
/*else be the parent*/
global+=2;
test+=2;
printf("global=%d test=%d Parent,my PID is %d\n",global,test,getpid());
exit(0);
//printf("global=%d test=%d Parent,my PID is %d",global,test,getpid());
//_exit(0);
}


编译执行,并分析结果:
[root@localhost root]# ./test
the test content!
fork test!
global=23 test=1 Child,my PID is 2751
global=24 test=2 Parent,my PID is 2750
可以看出父子进程打印出了各自的进程号和对应变量的值,
 显然 global 和 test 在父子进程间是独立的,
其各自的操作不会对对方的值有影响。将上述代码最后的两行代码替换为注释掉的_exit(0)行,重新编译,
查看结果,解释原因:
[root@localhost root]# ./test


the test content!
fork test!
global=23 test=1 Child,my PID is 2771
父进程的信息没有打印出来,其原因是:_exit()函数直接使进程停止运行,清除其使用的内存空间,
并销毁其在内核中的各种数据结构;而 exit()函数则在这些基础上作了一些包装,在执行退出之前加了若干
道工序。exit()函数在调用 exit 系统调用之前要检查文件的打开情况,把文件缓冲区中的内容写回文件,即
会 "清理 I/O 缓冲"。若将上述_exit(0)改为 exit(0),则肯定会有打印。另外,需要注意换行符\n 会引起 IO
的清理操作,若下面的语句 printf("global=%d test%d Parent,my PID is %d",global,test,getpid()); 加上\n,则调
用_exit(0)的结果和调用 exit(0)的结果是一样的。

实验二

2.vfork 的特点
将上述代码的 pid = fork();
 改为 pid = vfork();编译后运行结果如下:
[root@localhost root]# ./test
the test content!
fork test!
global=23 test=1 Child,my PID is 2849
global=25 test=3 Parent,my PID is 2848
可以看出,vfork 与 fork 区别在于共享的资源不一样,vfork 调用后,子进程先对 global 和 test 加 1,
父进程运行时,在其基础之上再加 2,得到上述运行结果。即 vfork 的特点是:在调用 execv 或者 exit 前子
进程对变量的修改会影响到父进程,即他们是共享的;
特别注意:父进程等待子进程调用 execv 或 exit 才继续执行。则若子进程依赖父进程的进一步动作时,
父进程又必须阻塞到子进程调用 execv 或者 exit 才会往下执行,此时就会造成“死锁”。读者可自己设计
测试一下这种“死锁”状态。



 fork 等函数编写执行命令实验
10.1 execv 函数族的使用
注意点:调用 execv 后,程序不再返回!在上述代码基础上,在子进程的退出代码前加入如下代码:
printf("global=%d test%d Child,my PID is %d\n",global,test,getpid());
if(execl("/bin/ps","ps","-au",NULL)<0)
perror("execl error!");
printf("this message will never be printed!\n");
exit(0);

编译运行后结果为:
[root@localhost root]# ./test
the test content!
fork test!
global=23 test=1 Child,my PID is 2909
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 2719 0.0 0.6 4360 1032 pts/1 S 23:14 0:00 /bin/bash
root 2908 0.0 0.1 1340 276 pts/1 R 23:38 0:00 ./test
root 2909 0.0 0.4 2684 736 pts/1 R 23:38 0:00 ps -au
global=25 test=3 Parent,my PID is 2908


10.2waitpid
waitpid 的作用是等待子进程退出并回收其资源,同时可以通过 WIFEXITED 等宏调用可以检测
子进程退出的状态。在第一个示例 fork 使用的代码基础上进行修改,添加检测进程退出状态的子函数,
参考代码如下:
void exit_check(int stat)
{
if (WIFEXITED(stat))
{ printf("exit normally!the return code is: %d \n",WEXITSTATUS(stat)); }
else if (WIFSIGNALED(stat))
{ printf("exit abnormally!the signal code is: %d \n",WTERMSIG(stat)); }
}

在父进程处理 global 和 test 变量前加入如下代码:
if (waitpid(pid,&stat,0) == pid)
{ exit_check(stat); } // the status of exit check

编译运行后结果为:
[root@localhost root]# ./test
the test content!
fork test!
global=23 test=1 Child,my PID is 2973
exit normally!the return code is: 0
global=24 test=2 Parent,my PID is 2972

可以看出父进程回收了退出的子进程的资源,检测到了它的退出状态。



本文转自lilin9105 51CTO博客,原文链接:http://blog.51cto.com/7071976/1418995,如需转载请自行联系原作者

相关文章
|
3月前
|
Linux 应用服务中间件 Shell
二、Linux文本处理与文件操作核心命令
熟悉了Linux的基本“行走”后,就该拿起真正的“工具”干活了。用grep这个“放大镜”在文件里搜索内容,用find这个“探测器”在系统中寻找文件,再用tar把东西打包带走。最关键的是要学会使用管道符|,它像一条流水线,能把这些命令串联起来,让简单工具组合出强大的功能,比如 ps -ef | grep 'nginx' 就能快速找出nginx进程。
424 1
二、Linux文本处理与文件操作核心命令
|
3月前
|
Linux
linux命令—stat
`stat` 是 Linux 系统中用于查看文件或文件系统详细状态信息的命令。相比 `ls -l`,它提供更全面的信息,包括文件大小、权限、所有者、时间戳(最后访问、修改、状态变更时间)、inode 号、设备信息等。其常用选项包括 `-f` 查看文件系统状态、`-t` 以简洁格式输出、`-L` 跟踪符号链接,以及 `-c` 或 `--format` 自定义输出格式。通过这些选项,用户可以灵活获取所需信息,适用于系统调试、权限检查、磁盘管理等场景。
294 137
|
3月前
|
安全 Ubuntu Unix
一、初识 Linux 与基本命令
玩转Linux命令行,就像探索一座新城市。首先要熟悉它的“地图”,也就是/根目录下/etc(放配置)、/home(住家)这些核心区域。然后掌握几个“生存口令”:用ls看周围,cd去别处,mkdir建新房,cp/mv搬东西,再用cat或tail看文件内容。最后,别忘了随时按Tab键,它能帮你自动补全命令和路径,是提高效率的第一神器。
684 57
|
2月前
|
存储 安全 Linux
Linux卡在emergency mode怎么办?xfs_repair 命令轻松解决
Linux虚拟机遇紧急模式?别慌!多因磁盘挂载失败。本文教你通过日志定位问题,用`xfs_repair`等工具修复文件系统,三步快速恢复。掌握查日志、修磁盘、验重启,轻松应对紧急模式,保障系统稳定运行。
414 2
|
3月前
|
缓存 监控 Linux
Linux内存问题排查命令详解
Linux服务器卡顿?可能是内存问题。掌握free、vmstat、sar三大命令,快速排查内存使用情况。free查看实时内存,vmstat诊断系统整体性能瓶颈,sar实现长期监控,三者结合,高效定位并解决内存问题。
276 0
Linux内存问题排查命令详解
|
3月前
|
Unix Linux 程序员
Linux文本搜索工具grep命令使用指南
以上就是对Linux环境下强大工具 `grep` 的基础到进阶功能介绍。它不仅能够执行简单文字查询任务还能够处理复杂文字处理任务,并且支持强大而灵活地正则表达规范来增加查询精度与效率。无论您是程序员、数据分析师还是系统管理员,在日常工作中熟练运用该命令都将极大提升您处理和分析数据效率。
277 16
|
4月前
|
Linux 网络安全 开发工具
技术栈:这50条最常用的 Linux 命令你一定要会!
建议多在终端中实践,遇到不懂的命令就用 man 或 --help 了解详情!
526 0
|
Ubuntu Unix Linux
操作系统--Linux操作实验报告
操作系统--Linux操作实验报告
操作系统--Linux操作实验报告
|
6月前
|
JSON 自然语言处理 Linux
linux命令—tree
tree是一款强大的Linux命令行工具,用于以树状结构递归展示目录和文件,直观呈现层级关系。支持多种功能,如过滤、排序、权限显示及格式化输出等。安装方法因系统而异常用场景包括:基础用法(显示当前或指定目录结构)、核心参数应用(如层级控制-L、隐藏文件显示-a、完整路径输出-f)以及进阶操作(如磁盘空间分析--du、结合grep过滤内容、生成JSON格式列表-J等)。此外,还可生成网站目录结构图并导出为HTML文件。注意事项:使用Tab键补全路径避免错误;超大目录建议限制遍历层数;脚本中推荐禁用统计信息以优化性能。更多详情可查阅手册mantree。
509 143
linux命令—tree
|
5月前
|
监控 Linux 网络安全
Linux命令大全:从入门到精通
日常使用的linux命令整理
824 14