一个简单的外壳程序的main历程

    在阅读《深入理解计算机操作系统》书的第八章看到这个简单的外壳程序的main,偶尔联想到自己工作中的调试程序,应该和这个实现方式是一样的,可能公司的会用到进程间的通信,但是原型基本都是这样的。具体看代码吗?代码有部分修改,同时我个人也有很多疑问大家求解?先贴代码吧!

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>

#define MAXARGS 128


pid_t FORK()
{
    pid_t pid;
    if((pid = fork()) < 0){
        printf("fork error!\n");
    }
    return pid;
}

/*解析命令行*/
int parseline(char *buf,char **argv)
{
    char *delim;
    int argc;
    int bg;

    /*将换行符转换成空格方便解析*/
    buf[strlen(buf) - 1] = ' ';

    /*忽略空格*/
    while(*buf && *buf == ' '){
        buf++;
    }

    argc = 0;
    while((delim = strchr(buf,' '))){
        argv[argc++] = buf;
        *delim = '\0';
        buf = delim + 1;
        while(*buf && *buf == ' '){
            buf++;
        }
    }
    argv[argc] = NULL;
    
    /*没有输入执行命令,返回1*/
    if(argc == 0){
        return 1;
    }

    /*是否后台运行
     *1:后台运行,0: 不是
     * */
    if(*argv[argc - 1] == '&'){
        bg = 1;
        argv[--argc] = NULL;
    }else{
        bg = 0;
    }
    return bg;

}


/*判断是退出程序还是忽略执行命令
 */
int builtin_command(char **argv)
{
    if(!strcmp(argv[0],"quit")){
        exit(0);
    }
    if(!strcmp(argv[0],"&")){//忽略 命令
        return 1;
    }
    return 0;

}
/*执行命令行
 * */
void eval(char *cmdline)
{
    char *argv[MAXARGS];
    char buf[MAXARGS];
    int bg;
    pid_t pid;
    char * envp[ ]={"PATH=/bin",0};

    strncpy(buf,cmdline,MAXARGS);
    bg = parseline(buf,argv);
   
    if(argv[0] == NULL){//忽略空行
        return;
    }

    if(!builtin_command(argv)){
        if((pid = FORK()) == 0){//子进程运行代码
            if(execve(argv[0],argv,envp) < 0){
                printf("%s:command not found.\n",argv[0]);
                exit(0);
            }else{
                printf("1111111111111\n");
                exit(2);
            }
        }
        
        /*这个是个疑问???
         * 当父进程是后台运行时,子进程退出是不是有系统回收??*/
        if(pid > 0 && !bg){
            int status;
            if(waitpid(pid,&status,0) < 0){
                printf("waitfg:waited,errr\n");
            }else{
                printf("%d,exit!\n",pid);
            }
        }else{
            printf("%d %s",pid,cmdline);
        }
    }
    return;

}

int main()
{
    char cmdline[MAXARGS];

    while(1){
        printf("[jsh_dbug] > ");
        //从终端输入
        fgets(cmdline,MAXARGS,stdin);
        if(feof(stdin)){
            exit(0);
        }
        //执行程序
        eval(cmdline);
    }
}


目前不理解的问题:

1、当程序运行的后台时,创建的子进程退出时的是有操作系统回收的吗?在代码中看到这样的处理机制,当运行程序后,在终端输入命令后,结尾加 & 符号,不同的处理。

[jsh@localhost 8]$ ./a.out 
[jsh_dbug] > /bin/pwd
/home/jsh/mystudy/com/8
9285,exit!
[jsh_dbug] > 
[jsh_dbug] > /bin/pwd &
9289 /bin/pwd &
[jsh_dbug] > /home/jsh/mystudy/com/8

[jsh_dbug] > quit
[jsh@localhost 8]$ 

2、这个疑问可能和这个代码没有什么关系,是关于fork函数的疑问,看下面代码吧


  
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>

pid_t FORK()
{
    pid_t pid;
    if((pid = fork()) < 0){
        printf("fork error!\n");
    }
    return pid;

}
#if 0
int main()
{
        printf("d");
    if(FORK() == 0){
     //   sleep(1);
   //     printf("a");
          exit(0);
    } 
       // printf("b");
       // waitpid(-1,NULL,0);
    
    printf("c");
    exit(0);

}
#endif

#if 
int main()
{
    int status;
    pid_t pid;
    printf("Hello!\n");
    pid = FORK();
    if(pid == 0){
    printf("%d\n",!pid);
    }

    if(pid != 0){
        if(waitpid(-1,&status,0) >  0){
            if(WIFEXITED(status) != 0)
                printf("%d\n",WEXITSTATUS(status));
        }
    }
    printf("BYE\n");
    exit(2);
}
#endif

上面代码中有2个mian函数,先执行下面的打印如下:

[jsh@localhost 8]$ ./a.out 
Hello!
1
BYE
2
BYE

当执行上面的代码时

[jsh@localhost 8]$ ./a.out 
dc[jsh@localhost 8]$ d

问题是 在fork 之前分别打印了 d 和hello    第一个hello打印一个,第二d打印2个,为什么?


  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值