相关系统调用
fork
wait
exec系列
exit
一个shell的主循环主要由下面的循环组成:
while(!end_of_input)
get command
execute command
wait for command to finish
至于fork wait exec这些系统调用不再赘述.
pid_t wait(int *status)
有一点,wait阻塞调用它的程序直到子进程结束,返回结束进程的PID,父进程通过传给wait的参数中获取子进程以何种方式退出。如果子进程调用exit退出,那么内核把exit的返回值存放到这个整数变量中的高八位,如果进程是被杀死的,那么内核将信号序号存放在这个变量的低7位,中间一位用来指明发生错误并产生了core dump。
一般通过下面示例在这样获取子进程状态
/*************************************************************************
> File Name: waitdemo.c
> Author: vinsanity
> Mail: skctvc15@163.com
> Created Time: 2014年03月29日 星期六 16时58分24秒
************************************************************************/
#include<stdio.h>
#include<sys/wait.h>
#include<sys/types.h>
#include<stdlib.h>
const int DELAY = 5;
int
main()
{
int newpid;
void child(),parent();
printf("before : mypid is %d\n",getpid());
if((newpid = fork()) == -1)
perror("fork");
else if(newpid == 0)
child(DELAY);
else
parent(newpid);
return 0;
}
void
child(int delay)
{
printf("child %d here .will sleep for %d seconds\n",getpid(),delay);
sleep(delay);
printf("child is done,exit\n");
exit(17);
}
void
parent(int childpid)
{
int wait_rv;
int child_status;
int high_8,low_7,bit_7;
wait_rv = wait(&child_status);
printf("done waiting for %dwait return :%d\n",childpid,wait_rv);
high_8 = child_status >> 8;
low_7 = child_status & 0x7f;
bit_7 = child_status & 0x80;
printf("status :exit = %d,sig = %d,core = %d",high_8,low_7,bit_7);
}
基本的一个shell实现如下:
/*************************************************************************
> File Name: psh1.c
> Author: vinsanity
> Mail: skctvc15@163.com
> Created Time: 2014年03月29日 星期六 16时13分20秒
************************************************************************/
#include<string.h>
#include<signal.h>
#include<stdio.h>
#include<signal.h>
#include<string.h>
#include<stdlib.h>
#define MAXARGS 20
#define ARGLEN 100
int
main(){
char *arglist[MAXARGS+1];
int numargs;
char argbuf[ARGLEN];//read stuff
char *makestring(); //malloc etc
numargs = 0;
while(numargs < MAXARGS)
{
printf("Arg[%d]?",numargs);
if(fgets(argbuf,ARGLEN,stdin) && *argbuf != '\n')
arglist[numargs++] = makestring(argbuf);
else {
if(numargs >0){ //any args?
arglist[numargs] = NULL; //close list
execute(arglist); //do it
numargs = 0; //reset
}
}
}
return 0;
}
int
execute(char *arglist[])
{
int pid,exit_status;
char * e="exit";
pid = fork();
switch(pid){
case -1:
perror("fork failed");
exit(1);
case 0:
signal(SIGINT,SIG_IGN);
execvp(arglist[0],arglist);
perror("exec failed");
exit(1);
default :
while( wait(&exit_status)!=pid )
;
printf("child exited with status %d ,%d/n",exit_status>>8,exit_status&0x7f);
}
}
char *
makestring( char * buf )
{
char *cp;
buf[strlen(buf)-1] = '\0';
cp = malloc(strlen(buf)+1);
if(cp == NULL)
{
fprintf(stderr,"no memory\n");
exit(1);
}
strcpy(cp,buf);
return cp;
}