Linux C编程--进程介绍7--综合应用实例

来源:互联网 发布:定额计价软件 编辑:程序博客网 时间:2024/05/30 04:09

第一个实例重点说明fork和exec系统函数

该实例是一个交互式命令处理程序,它能完成Linux系统标准Shell的小部分功能,具体功能如下所述:

1.提交命令的参数最多为8个

2.可前,后台执行

3.一命令行中可同时拥有多个命令,彼此之间用分号隔开


实现程序的主流程如下:

for(;;)

{

output("mini_SH-->");

readcmd();

docommand();

}


下面给出源代码:

#include <sys/types.h>#include <unistd.h>#include <stdio.h>#define MAXARG 10#define LINSIZ 80#define CMDSIZ 8extern char **environ;char *quit="quit.quit";char cmdbuf[CMDSIZ][LINSIZ];int cmdflag[CMDSIZ];int main(){int i;for( ; ;){printf("mini_SH-->");for(i=7;i>=0;i--){cmdflag[i]=0;/* */cmdbuf[i][0]='\0';}if(i=readcmd())/* */docommand(i);/* */elseprintf("read command failed, try again!!!\n");}}readcmd(){char c,*p;int i=0;p=cmdbuf[0];while((c=getchar())!='\n'){if(c==';'){*p='\0';if(++i==6)return(++i);p=cmdbuf[i];}else if(c=='&'){cmdflag[i]=1;}else*p++=c;}*p='\0';return(++i);}docommand(int i){int j, stat, pid;char *argl[MAXARG], args[LINSIZ];char c, *argsp, **arglp, *p;for(j=0;j<i;j++){arglp=argl;argsp=args;p=cmdbuf[j];while((c=*p++)!='\0'){while(c==' '|| c=='\t')c=*p++;if(c=='\0'){*argsp++='\0';break;}*arglp++=argsp;while(c!=' '&&c!='\t'&&c!='\0'){*argsp++=c;c=*p;if(c)  p++;}*argsp++='\0';}*arglp=(char *)0;if(strcmp(argl[0],quit)==0){ printf("Bye Bye!\n");exit(0);}if((pid=fork())==0){if(cmdflag[j]) setpgrp();execve(argl[0],argl,environ);printf("Returned from execve: %s\n",cmdbuf[i]);exit(10);}else{if(! cmdflag[j])while(wait(&stat)!=pid);}}}

程序代码说明:

(1) 数据结构说明。该mini_SH定义了每条命令所能使用的最大参数个数为MAXARG,定义为10。每条命令的字符缓存数组由LINSIZ决定,最大为80,一次提交的命令个数由CMDSIZ决定,最多8个。字符指针quit存放退出命令字符串,它已经赋值为quit.quit,二维数组cmdbuf存放标准输入读到的字符串,而数组cmdflag决定该命令以何种方式执行,0为前台,1为后台。

(2)main函数。按主流程的设计思想实现,在无限循环for中,首先打印命令接收提示符mini_SH-->,将用户输入的命令字符串,通过函数readcmd得到并存储在cmdbuf二维数组中,readcmd返回一次提交的用分号隔开的命令个数。而函数docommand执行存放在cmdbuf中的命令。

(3)readcmd函数。将用户从标准输入提交的一行命令,按分号为界,分别存放命令缓冲区cmdbuf中,如果命令字符中有“&”符,将命令标志数组cmdflag的相应位置为1,每次提交命令时,该数组字段被清为0,并返回提交的命令个数。

(4)docommand函数。在for循环中,每次执行一条命令。用户提交的命令按顺序存放在数组cmdbuf中,while循环将命令执行的参数以空格或制表符为分界线,将字符型的指针数组argl分别指向相应的字符串,argl[0]指向该命令字符串,arg[1]是该命令的第一个参数,以此类推,最后一个参数为空指针。对于每一个参数增加一个空字符”\0“。如果命令字符串为定义的退出该命令字符串quit.quit,则调用exit系统函数退出执行,否则,调用fork生成子进程。如果设置后台标志位,则重新设置进程组号,使用带环境变量的系统调用execve执行用户提交用户执行的命令,如该命令以后台方式执行,则父进程不等待该命令执行完后就可执行新的命令。否则,父进程使用wait函数等待子进程执行暂停或终止。


该程序是一个完整的程序,编译后生成mini_sh命令,一下是在mini_sh命令控制下,用户提交命令的执行情况:

$ ./mini_sh

mini_SH-->/bin/date

2011年12月05日 星期一 23:37:19 PST

mini_SH-->/bin/who

Returned from execve:

mini_SH-->/bin/pwd;/bin/date

/home/lxy/test1/BruceZhang

2011年12月05日 星期一 23:37:19 PST

mini_SH-->quit.quit

Bye Bye!

原创粉丝点击