fork()

  • 计算机程序设计中的分叉函数。返回值: 若成功调用一次则返回两个值,子进程返回0,父进程返回子进程标记;否则,出错返回-1。

    fork函数将运行着的程序分成2个(几乎)完全一样的进程,每个进程都启动一个从代码的同一位置开始执行的线程。这两个进程中的线程继续执行,就像是两个用户同时启动了该应用程序的两个副本。
mybash 版本一

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
char command[256];
void main()
{
int rtn; /*子进程的返回数值*/
while(1) { printf( ">" );
gets( command, 256, stdin );
command[strlen(command)-1] = 0;
if ( fork() == 0 ) {
execlp( command, NULL ); perror( command );
exit( errno );
}
else {
wait ( &rtn );
printf( " child process return %d\n", rtn );
}
}
}

这个版本不能得到正确结果,会打印错误提示 ,但是可以根据运行结果的内容发现,fork()的返回值有两个,一个是0代表生成的子程序,还有一个代表的父程序。

exec( )函数族

  • 在Linux中要使用exec函数族。系统调用execve()对当前进程进行替换,替换者为一个指定的程序,其参数包括文件名(filename)、参数列表(argv)以及环境变量(envp)。exec函数族当然不止一个,但它们大致相同,在 Linux中,它们分别是:execl,execlp,execle,execv,execve和execvp,可以通过manexec命令来了解它们的具体情况。
  • 在这个函数族的函数使用的过程中主要是注意字符串数组的存放,目前看来所有的程序问题主要集中在这一部分,在这里先贴一个在网上查到的输入代码,之后再仔细研究
 numargs=0;
while(numargs<MAXARGS){
printf("Arg[%d]?",numargs);
if(fgets(argbuf,ARGLEN,stdin)&&*argbuf!='\n')
arglist[numargs++]=makestring(argbuf);
else{
if(numargs>0){
arglist[numargs]=NULL;
execute(arglist);
numargs=0;
}
}
}

wait()

  • wait(等待子进程中断或结束)

    相关函数 waitpid,fork

    表头文件
#include<sys/types.h>
#include<sys/wait.h>
pid_t wait (int * status);
  • 函数说明

wait()会暂时停止目前进程的执行,直到有信号来到或子进程结

束。如果在调用wait()时子进程已经结束,则wait()会立即返

回子进程结束状态值。子进程的结束状态值会由参数status 返回,

而子进程的进程识别码也会一快返回。如果不在意结束状态值,则

参数status 可以设成NULL。子进程的结束状态值请参考waitpid()。

返回值

如果执行成功则返回子进程识别码(PID),如果有错误发生则返回

-1。失败原因存于errno 中。

waitpid()

waitpid()会暂时停止目前进程的执行,直到有信号来到或子进程结束。waitpid的返回值比wait稍微复杂一些,一共有3种情况:

1.当正常返回的时候,waitpid返回收集到的子进程的进程ID;
2.如果设置了选项WNOHANG,而调用中waitpid发现没有已退出的子进程可收集,则返回0;
3.如果调用中出错,则返回-1,这时errno会被设置成相应的值以指示错误所在;
当pid所指示的子进程不存在,或此进程存在,但不是调用进程的子进程,waitpid就会出错返回,这时errno被设置为ECHILD;

exit

  • exit()通常是用在子程序中用来终结程序用的,使用后程序自动结束,跳回操作系统。
  • exit(0) 表示程序正常退出,exit⑴/exit(-1)表示程序异常退出。
(1)exit和return 的区别: 

a.exit是一个函数,有参数。exit执行完后把控制权交给系统 

b.return是函数执行完后的返回。renturn执行完后把控制权交给调用函数。 

(2)exit和abort的区别: 

a.exit是正常终止进程 

b.about是异常终止。

getpid()

getpid是一种函数,功能是取得进程识别码,许多程序利用取到的此值来建立临时文件,以避免临时文件相同带来的问题。通过在虚拟机中运行可以看出,getpid()的返回值每次都不一样。

getppid()

getpid返回当前进程标识,getppid返回父进程标识。

sleep()

函数功能: 执行挂起一段时间;

Sleep函数的一般形式:

Sleep(unsigned long);//参数即为挂起时间

pause()

alarm(time);执行之后告诉内核,让内核在time秒时间之后向该进程发送一个定时信号,然后该进程捕获该信号并处理;

pause()函数使该进程暂停让出CPU,但是该函数的暂停和前面的那个sleep函数的睡眠都是可被中断的睡眠,也就是说收到了中断信号之后再

重新执行该进程的时候就直接执行pause()和sleep()函数之后的语句;

可以用alarm()函数中断pause();

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h> void sig_handler(int num)
{
printf("receive the signal %d.\n", num);
alarm(2);
} int main()
{
signal(SIGALRM, sig_handler);<br>
alarm(2);<br>
while(1){
pause();
printf("pause is over.\n");
}
exit(0);
}

setenv

函数说明 setenv()用来改变或增加环境变量的内容。参数name为环境变量名称字符串。参数 value则为变量内容,参数overwrite用来决定是否要改变已存在的环境变量。如果没有此环境变量则无论overwrite为何值均添加此环境变量。若环境变量存在,当overwrite不为0时,原内容会被改为参数value所指的变量内容;当overwrite为0时,则参数value会被忽略。返回值 执行成功则返回0,有错误发生时返回-1。

unsetenv

int unsetenv(const char *name);

删除name的定义,即使不存在也不算出错。

主要用于setenv()函数使用过后释放空间。

  • 伪代码

int main(){

//从终端读取要执行的命令
//fork()产生子进程执行此命令
//如果exec函数返回,表明没有正常执行命令,打印错误信息perro()
//父进程, 等待子进程结束,并打印子进程的返回值wait(&rtn) }
  • 产品代码

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <limits.h> void main()
{ char *command[3];
command[0] = "ls";
command[1] = "-l";
command[2] = 0; int s,i=0;
int rtn;
printf( ">" );
//printf("%s %s %s",command[1],command[2],command[3]);
printf("%s",command[0]);
i=0;
s=fork();
if ( s== 0 ) {
//printf("%d\n",s);
execvp( command[0], command ); //perror( command ); exit( errno );
}
else { //printf("%d\n",s); wait ( &rtn ); printf( " child process return %d\n", rtn ); } }
  • 后续修改

参考教材第八章parseline等关于输入字符串的代码,问题得到了解决。



注:show为 2进制可执行文件,所以显示乱码。

参考资料

深入浅出---unix多进程编程之wait()和waitpid()函数

Sleep函数的真正用意

getenv putenv setenv和unsetenv详解

mybash的编写与调试的更多相关文章

  1. OC编写使用调试器

    OC编写使用调试器 编写代码免不了,Bug.那么Debug就是程序员的必备技能了.本文和大家一起探讨,如何在应用开发编写代码过程中,使用日志项消息:以及使用动作.条件.迭代控制增强断点. 记录信息 在 ...

  2. MEX文件编写和调试

    作者kaien,2010/02/16 以前我写过一篇文章,详细的介绍过MEX的格式,语法,编译,调试等.可惜记不清放在哪里了.而最近又用到MEX编程,所以只能重新温习一番.时间有限,只记下简要流程和注 ...

  3. VsCode编写和调试.NET Core

    本文转自:https://www.cnblogs.com/Leo_wl/p/6732242.html 阅读目录 使用VsCode编写和调试.NET Core项目 回到目录 使用VsCode编写和调试. ...

  4. 如何快速编写和调试 Emit 生成 IL 的代码

    .NET Core/.NET Framework 的 System.Reflection.Emit 命名空间为我们提供了动态生成 IL 代码的能力.利用这项能力,我们能够在运行时生成一段代码/一个方法 ...

  5. 一个项目的Makefile编写及调试

    父Makefile 在src目录下包含很多文件夹,那么需要遍历所有的目录执行Makefile,那么给一个在src目录下的Makefile. # 需要排除的目录 exclude_dirs := incl ...

  6. 使用PyCharm实现远程编写并调试代码

    使用PyCharm实现远程编写并调试代码 版权声明:本文为博主原创文章,转载请注明出https://www.cnblogs.com/wenqiangit/p/9771947.html 因为工作中使用的 ...

  7. Ubuntu\Linux 下编写及调试C\C++

    一.在Ubuntu\Linux 下编写及调试C\C++需要配置基本的环境,即配置gcc编译器.安装vim编译器,具体配置安装步骤我在这里就不多说了. 二.基本环境配置完了我们就可以进入自己的程序编写了 ...

  8. 使用VsCode编写和调试.NET Core项目

    ​ 本来我还想介绍以下VSCode或者donet core,但是发现都是废话,没有必要,大家如果对这个不了解可以直接google这两个关键字,或者也根本不会看我这边文章. ​ 好直接进入主题了,本文的 ...

  9. Spark程序开发-环境搭建-程序编写-Debug调试-项目提交

    1,使用IDEA软件进行开发. 在idea中新建scala project, File-->New-->Project.选择Scala-->Scala 2,在编辑窗口中完成Word ...

随机推荐

  1. java一些使用

    随机数.输入.byte数组和string转换 一些可能会使用到的方法.供及时查找 ########################random类使用 Random random = new Rando ...

  2. SQL脚本修改表结构

    SQL脚本修改表结构 新建表:create table [表名]([自动编号字段] int IDENTITY (1,1) PRIMARY KEY ,[字段1] nVarChar(50) default ...

  3. vi编辑器的命令详情

    选定文本块,使用v复制选定块到缓冲区,使用y复制整行,用yy在同一编辑窗打开第二个文件,用:sp [filename]在多个编辑文件之间切换,用^ww剪切块,用d剪切整行用dd粘贴缓冲区中的内容,用p ...

  4. Mac原生Terminal快速登录ssh

    1. 创建rsa key 在终端中输入以下命令: ssh-keygen -t rsa 完成之后可以在~/.ssh目录下找到公钥和私钥     如果你与我一样有使用gitlab,那么这个秘钥应该已经存在 ...

  5. 【[ZJOI2012]灾难】

    好像很久之前就看过这道题,大概是刚学\(LCA\)的时候 之后当时肯定是不会的呀 现在发现这道题并不是非常难 首先我们发现这个灭绝的关系非常像一棵树,我们建出这个灭绝树求一个前缀和就可以啦 那么应该怎 ...

  6. P2149 [SDOI2009]Elaxia的路线

    题目描述 最近,Elaxia和w**的关系特别好,他们很想整天在一起,但是大学的学习太紧张了,他们 必须合理地安排两个人在一起的时间. Elaxia和w**每天都要奔波于宿舍和实验室之间,他们 希望在 ...

  7. 7、Web Service-IDEA-jaxws规范下的 服务端/客户端 开发

    前提简介:这里之后即使基于IDEA进行开发的,风格与之前有些不同之处! 1.服务端的开发 1.创建新的项目 2.pom.xml 添加开发时所需要的依赖 <?xml version="1 ...

  8. 《metasploit渗透测试魔鬼训练营》学习笔记第七章--社会工程学

    五.社工工程学     5.1社会工程系框架          5.1.1信息搜集                 maltego是一个高度自动化的信息搜集工具,集成在BT5中,如果国内网络环境使用时 ...

  9. 如何彻底修改eclipse中的名称

    一.右键工程:Refactor->Rename,或选中工程按F2,修改名称二.修改项目目录下:.project文件 <?xml version="1.0" encodi ...

  10. PAT——1047. 编程团体赛

    编程团体赛的规则为:每个参赛队由若干队员组成:所有队员独立比赛:参赛队的成绩为所有队员的成绩和:成绩最高的队获胜. 现给定所有队员的比赛成绩,请你编写程序找出冠军队. 输入格式: 输入第一行给出一个正 ...