zoukankan      html  css  js  c++  java
  • 基于fork(),execvp()和wait()实现类linux下的bash——mybash

    基于fork(),execvp()和wait()实现类linux下的bash——mybash

    预备知识

    • fork():fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程,也就是两个进程可以做完全相同的事,但如果初始参数或者传入的变量不同,两个进程也可以做不同的事http://blog.csdn.net/jason314/article/details/5640969
      • 重点是后一句话,如果初始参数或者传入变量不同,两个进程也可以做不同的事,意思就是虽然父进利用fork()函数创造了一个和自己完全一致的子进程,但由于子进程执行指针开始至位于fork()函数后,意思就是子进程不会再执行一次fork()上面的代码,所有的fork()前定义的变量,都将保持初始化的值。
    • wait():进程一旦调用了wait,就立即阻塞自己,由wait自动分析是否当前进程的某个子进程已经退出,如果让它找到了这样一个已经变成僵尸的子进程,wait就会收集这个子进程的信息,并把它彻底销毁后返回;如果没有找到这样一个子进程,wait就会一直阻塞在这里,直到有一个出现为止,wait其实比较好理解http://blog.sina.com.cn/s/blog_759803690101aqeq.html
    • execvp():exec系统调用会从当前进程中把当前程序的机器指令清除,然后在空的进程中载入调用时指定的程序代码,最后运行这个新的程序http://www.linuxidc.com/Linux/2011-10/44527.htm.
      • 这样的定义就意味着,所有execvp()后面的代码都将不被执行,相当于在主函数里“重写”了一遍传入execvp函数中的程序,又在紧接着在后面加了句exit(1);这样往往带来不便,但根据定义,我们可以将fork和execvp结合,从而保护父进程。

    产品伪代码

    Step1:读入用户输入的指令;
    Step2:调用fork函数生成一个子进程,并将fork返回的pid值赋给fpid;
    Step3:调用wait函数,传入null;
    Step4:判断fpid是否为零,如果为零执行Step5;如果不为零,执行Step6;
    Step5:调用execvp函数,并把用户输入的指令传进去;
    Step6:返回Step1;
    

    产品代码

    #include	<stdio.h>
    #include	<stdlib.h>
    #include	<string.h>
    #include    <unistd.h>
    #include    <sys/types.h>
    #include    <sys/wait.h>
    
    #define	MAXARGS		20				
    #define	ARGLEN		100				
    
    int execute( char *arglist[] )
    {
    	execvp(arglist[0], arglist);		
    	perror("execvp failed");
    	exit(1);
    }
    
    char * makestring( char *buf )
    {
    	char	*cp;
    
    	buf[strlen(buf)-1] = '';		
    	cp = malloc( strlen(buf)+1 );		
    	if ( cp == NULL ){			
    		fprintf(stderr,"no memory
    ");
    		exit(1);
    	}
    	strcpy(cp, buf);		
    	return cp;			
    }
    int mybash(char *arglist[])
    {
    	
    	int flag=0;
    	flag=fork();
    	wait(NULL);
    	if(flag==0)	
    	execute( arglist );
    else return 1;
    }
    
    
    
    
    

    测试代码

    #include<stdio.h>
    #include	<string.h>
    #include"head.h"
    int mybash(char *arglist[]);
    int test1()
    {
    char *test1[10],*test2[10],*test3[10],*test4[10],*test5[10],*test6[10];
    test1[0]="ls";
    test1[1]="-l";
    test1[2]=0;
    
    test2[0]="od";
    test2[1]="-tc";
    test2[2]="-tx1";
    test2[3]="12.txt";
    test2[4]=0;
    
    test3[0]="mkdir";
    test3[1]="success";
    test3[2]=0;
    
    test4[0]="git";
    test4[1]="add";
    test4[2]=".";
    test4[3]=0;
    
    test5[0]="git";
    test5[1]="commit";
    test5[2]="-m";
    test5[3]=""test11"";
    test5[4]=0;
    
    test6[0]="git";
    test6[1]="push";
    test6[2]="origin";
    test6[3]="master";
    test6[4]=0;
    
    int flag=0;
    if(flag=mybash(test1)==1)printf("
    %s %s test Success!
    ",test1[0],test1[1]);
    
    flag=0;
    if(flag=mybash(test2)==1)printf("
    %s %s %s %s test Success!
    ",test2[0],test2[1],test2[2],test2[3]);
    
    flag=0;
    if(flag=mybash(test3)==1)printf("
    %s %s test Success!
    ",test3[0],test3[1]);
    
    flag=0;
    if(flag=mybash(test4)==1)printf("
    %s %s %s test Success!
    ",test4[0],test4[1],test4[2]);
    
    flag=0;
    if(flag=mybash(test5)==1)printf("
    %s %s %s %s test Success!
    ",test5[0],test5[1],test5[2],test5[3]);
    
    flag=0;
    if(flag=mybash(test6)==1)printf("
    %s %s %s %s test Success!
    ",test6[0],test6[1],test6[2],test6[3]);
    
    return 0;
    }
    
    • 测试运行截图

    问题及解决方法

    • 问题1:因为使用的是execvp函数是放在主函数里的,往往都会直接终结掉父进程,这是主要问题;
    • 问题1解决:调用fork函数生成一个子进程,并且只允许execvp运行在子进程中,这样execvp终结掉的就只是子进程,而不会影响父进程,而对于fork函数完整复制父进程的子进程也会因为调用了execvp而及时终结掉,不会导致一个无谓的循环。
    • 问题2:怎么实现只让execvp运行在子进程,而不去影响父进程
    • 问题2解决:这是根本问题,解决了才能使得mybash正常的去运行去循环,因为fork函数的特性就是完整复制父进程,但子进程永远都是从fork后面执行意思就是,fork前面的变量将保持初始化的值,而不受fork前面的代码影响,所以,这里可以使用fpid来作为flag判断这是一个子进程还是一个父进程,如果是一个子进程那么就运行execvp,如果不是就返回继续执行父进程;

    运行截图

    码云链接

  • 相关阅读:
    HTML表单元素
    hadoop编程技巧(3)---定义自己的区划类别Partitioner
    SDUTOJ 2054 双向链表
    serialVersionUID行动
    笔试
    循环队列
    css @media认识
    大约ActionContext.getContext()使用体验
    在希望的田野上--生物柴油(Biodiesel)光明的未来
    SD卡FAT32获得高速的文件格式(图文介绍)
  • 原文地址:https://www.cnblogs.com/elevator/p/7698864.html
Copyright © 2011-2022 走看看