血的教训!希望还没备份自己重要文件的朋友们抓紧备份一份

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <unistd.h>
#include <sys/wait.h>
#include<sys/stat.h>
#include <fcntl.h>  //O_CREAT


#define Miku_RL_BUFFERSIZE 1024
#define MAXPATH 256
#define Miku_SEC_BUFFER    64
#define Miku_SEC_DELIM  " \t\r\n"
// \t 的意思是 横向跳到下一制表符位置 \r 的意思是 回车 \n 的意思是回车换行

char *Miku_read_line(void)
{
    int buffersize = Miku_RL_BUFFERSIZE ;                  //空间大小
    int position  =0 ;                                  //存入buffer的位置index
    
    int c ;                                             //每次所读取的 字符! 注意是字符!不是整数
                                                        //因为之后要判断EOF 这是一个int类型

    char * buffer = malloc(sizeof(char)* buffersize );  //创建一个数组 指向空间 的指针
    
    //检查缓冲区是否创建成功
    if(!buffer){
        printf("Miku: memoery allocation wrong !");
        exit(EXIT_FAILURE);
    }
    
    while(1){
        //字符获取
        c = getchar();
        //判断终止符EOF 和 换行符?
        if(c=='"'){
            continue;
        }
        else if(c == EOF || c =='\n'){
            buffer[position] = '\0';
            return buffer ;
        }
        else{
            buffer[position]= c ;
            position++;
        }
        
        //如果超出了我们限定的数组大小。
        if( position >= buffersize ){
            //扩大数组容量
            buffersize += Miku_RL_BUFFERSIZE;
            buffer = realloc(buffer, buffersize);
            
            if(!buffer ){
                printf("Miku: memoery allocation wrong !");
                exit(EXIT_FAILURE);
            }
        }
    }
}

char **Miku_split_line( char* line ){
    
    int bufsize = Miku_SEC_BUFFER;
    int position = 0;
    char **total_sec = malloc( sizeof(char*)*bufsize );
    char *sec ;
    
    if( !total_sec ){
        printf("Miku: memoery allocation wrong !");
        exit(EXIT_FAILURE);
    }
    
    sec =strtok( line , Miku_SEC_DELIM );
    while( sec!=NULL ){
        total_sec[position] = sec ;
        position++ ;
        //容量监控
        if(position >=bufsize){
            bufsize  +=Miku_SEC_BUFFER;
            total_sec = realloc(total_sec, bufsize);
            if(total_sec==NULL){
                printf("Miku: memoery allocation wrong !");
                exit(EXIT_FAILURE);
            }
        }
        sec = strtok(NULL ,Miku_SEC_DELIM );
        // 这个地方的参数NULL 表示接着上一个被找到的 位置继续往后查找。
    }
    total_sec[position] = NULL ; //封上
    return total_sec;
}



/*        内置函数         */
int Miku_cd(char **args);
int Miku_help(char **args);
int Miku_exit(char **args);
int Miku_info(char **args);
int Miku_pwd(char **args);


//一个数组 其中的元素类型为 char型指针(即指向字符串首字符)
char *builtin_str[] = {
  "cd",
  "help",
  "exit",
  "info",
  "pwd"
};

int (*builtin_func[]) (char **) = {
  &Miku_cd,
  &Miku_help,
  &Miku_exit,
  &Miku_info,
  &Miku_pwd
};


int number_of_bulidins (){
    return sizeof(builtin_str)/sizeof(char*);
}


int Miku_cd(char** args){
    if(args[1] == NULL ){
        printf("please enter a dirctory ");
    }
    else {
        if(chdir(args[1]) != 0){
              perror("Miku_shell"); //返回值:成功返回0 ,失败返回-1
        }
    }
    
    return 1;
}


int Miku_help(char **args){
    int i;
    printf("*********************Miku Shell*********************\n");
    printf("The bulidin functions are as follows\n");

    for (i = 0; i < number_of_bulidins(); i++) {
      printf("  %s\n", builtin_str[i]);
    }

    return 1;
}


int Miku_exit (char **args){
    return 0;
}


int Miku_info(char **args){
    printf("“COMP2211 Simplified Shell by Luo Ruidi sc17rl@leeds.ac.uk.”\n");
    return 1;
}

int Miku_pwd(char **args){
    char buffer[MAXPATH];
    getcwd(buffer,MAXPATH);
    printf("The current directoryis:%s\n",buffer);
    return 1;
}



// *************系统调用,  //


int Miku_launch(char** args){
    
    pid_t pid ;  //进程 ID
  
    int status;
    
    pid = fork();  /*
                    在父进程中返回 >0
                    在子进程中返回  0
                    错误返回。     <0   由其返回值 可判断实在 父 还是在子
                    */
    if(pid < 0 ){
        perror("Miku_shell");
    }
    else if (pid == 0){
        //返回-1 表示失败
        if(  execvp(args[0], args)  == -1 )
        {
             perror("Miku_shell");
        }
    }
    else {
        do {
            waitpid(pid ,&status ,WUNTRACED);
        }while(!WIFEXITED(status) && !WIFSIGNALED(status));
    }
    
    return 1;
    
}

/*
   输入ex + 可执行文件名 + 传递的参数
 */

int Miku_Ex(char** args){
    
    pid_t pid ;
    int status;
    pid = fork();
    if(pid < 0 ){
        perror("Miku_shell");
    }
    else if (pid == 0){
        if(  execvp(args[1], args)  == -1 )
        {
             perror("Miku_shell");
        }
    }
    else {
        do {
            waitpid(pid ,&status ,WUNTRACED);
        }while(!WIFEXITED(status) && !WIFSIGNALED(status));
    }
    return 1;
    
}



/*
 
 */

int Miku_grep(char** args){
    pid_t pid ;
    int status;
    pid = fork();
    if(pid < 0 ){
        perror("Miku_shell");
    }
    else if (pid == 0){
        if(  execlp("grep","grep" ,args[1],args[2],args[3])  == -1 )
        {
             perror("Miku_shell");
        }
    }
    else {
        do {
            waitpid(pid ,&status ,WUNTRACED);
        }while(!WIFEXITED(status) && !WIFSIGNALED(status));
    }
    return 1;

}

char readmes[25] ;
int Miku_pipeline(char** args){
   int chidB ,chidC;
    int pipefd[2];
    
    //创建 管道
    if( pipe(pipefd)==-1 ){
        printf("pipe fault\n");
        return 1;
    }
    if(!(chidB =fork() ) ){
        close(pipefd[1]);  //在B中 关闭他的写pipe权限 只让他读
        close(0)  ;// 0 -> stdin
        dup2(pipefd[0], 0); //将B的读区位置 设为 管道的0 口
       
        read(pipefd[0], readmes, 25);
        char *args1[] = {readmes, NULL};
        close(pipefd[0]);
        execve(args[4],args1,NULL);
    }
    close(pipefd[0]); // 在A 主程序中
    if(!(chidC =fork() ) ){
             close(pipefd[0]);  //在C中 关闭他的读pipe权限 只让他输出
             close(1)  ;// 1 -> stdout
             dup2(pipefd[1], 1); //将C的输出位置 设为 管道的1 口
             execve(args[1],NULL,NULL);
         }
    close(pipefd[1]); // 在主程序中
    wait4(chidB, NULL, 0, NULL);
  //  printf("%s\n", "OVER!");
   

    return 1;
}

int Miku_redirection(char **args){
    int fd = open("a.txt",O_CREAT|O_RDWR|O_TRUNC, S_IRUSR|S_IWUSR);
      if(fd<0){
          printf("Open Error!\n");
          return 0;
      }
    //  write(fd, "miku", strlen("miku"));
      pid_t pid;
      pid = fork();
      if(pid<0){
             printf("fork wrong\n");
         }
      else if(pid==0){   // 子进程
         close(1)  ;// 1 -> stdout
         dup2(fd, 1); //将C的输出位置 设为 管道的1 口
         execve(args[1],NULL,NULL);
          
         }
      else{
          
      }
      close(fd);
    return 1;
}


int Miku_execute(char **args){
    int i= 0 ;
    
    if(args[0] == NULL ){
        return 1;
    }
    
    for(i=0 ;i<number_of_bulidins() ;i++)
    {
        if (strcmp(args[0], builtin_str[i]) == 0 )
            return (*builtin_func[i])(args);
    }
    
   
   if( strcmp(args[0], "ex") == 0 ){

        if( strcmp(args[2], "|") == 0){
               Miku_pipeline(args);
               return 1;
           }
        else if (strcmp(args[2], ">") == 0){
           return Miku_redirection(args);
        }
        else{
        return Miku_Ex(args);
        }
    }
    else if (strcmp(args[0], "mygrep") == 0 ){
        return Miku_grep(args);
    }
    
    
    return Miku_launch(args);
    
}



void Miku_loop(void){
    
    
    //全都是 指针型。目的是啥?
    char *line  ;  //读取用户输入
    char **args ; //转译 输入?
    
    int  status = 0 ; //状态显示
    
    do{
        printf("Miku_Shell> "); //打出一个提示符 告知用户输入
        line = Miku_read_line();
        args = Miku_split_line(line);
        status = Miku_execute(args);
  
        free(line);
        free(args);
    }while(status);
    

}



int main(int argc, const char * argv[]) {


    Miku_loop();
    
    return 0;
    
}

 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <unistd.h>
#include <sys/wait.h>


#define Miku_RL_BUFFERSIZE 1024
#define Miku_SEC_BUFFER    64
#define Miku_SEC_DELIM  " \t\r\n"
// \t 的意思是 横向跳到下一制表符位置 \r 的意思是 回车 \n 的意思是回车换行

char *Miku_read_line(void)
{
    int buffersize = Miku_RL_BUFFERSIZE ;                  //空间大小
    int position  =0 ;                                  //存入buffer的位置index
    
    int c ;                                             //每次所读取的 字符! 注意是字符!不是整数
                                                        //因为之后要判断EOF 这是一个int类型

    char * buffer = malloc(sizeof(char)* buffersize );  //创建一个数组 指向空间 的指针
    
    //检查缓冲区是否创建成功
    if(!buffer){
        printf("Miku: memoery allocation wrong !");
        exit(EXIT_FAILURE);
    }
    
    while(1){
        //字符获取
        c = getchar();
        //判断终止符EOF 和 换行符?
        if(c=='"'){
            continue;
        }
        else if(c == EOF || c =='\n'){
            buffer[position] = '\0';
            return buffer ;
        }
        else{
            buffer[position]= c ;
            position++;
        }
        
        //如果超出了我们限定的数组大小。
        if( position >= buffersize ){
            //扩大数组容量
            buffersize += Miku_RL_BUFFERSIZE;
            buffer = realloc(buffer, buffersize);
            
            if(!buffer ){
                printf("Miku: memoery allocation wrong !");
                exit(EXIT_FAILURE);
            }
        }
    }
}

char **Miku_split_line( char* line ){
    
    int bufsize = Miku_SEC_BUFFER;
    int position = 0;
    char **total_sec = malloc( sizeof(char*)*bufsize );
    char *sec ;
    
    if( !total_sec ){
        printf("Miku: memoery allocation wrong !");
        exit(EXIT_FAILURE);
    }
    
    sec =strtok( line , Miku_SEC_DELIM );
    while( sec!=NULL ){
        total_sec[position] = sec ;
        position++ ;
        //容量监控
        if(position >=bufsize){
            bufsize  +=Miku_SEC_BUFFER;
            total_sec = realloc(total_sec, bufsize);
            if(total_sec==NULL){
                printf("Miku: memoery allocation wrong !");
                exit(EXIT_FAILURE);
            }
        }
        sec = strtok(NULL ,Miku_SEC_DELIM );
        // 这个地方的参数NULL 表示接着上一个被找到的 位置继续往后查找。
    }
    total_sec[position] = NULL ; //封上
    return total_sec;
}



/*        内置函数         */
int Miku_cd(char **args);
int Miku_help(char **args);
int Miku_exit(char **args);
int Miku_info(char **args);


//一个数组 其中的元素类型为 char型指针(即指向字符串首字符)
char *builtin_str[] = {
  "cd",
  "help",
  "exit",
  "info"
};

int (*builtin_func[]) (char **) = {
  &Miku_cd,
  &Miku_help,
  &Miku_exit,
  &Miku_info
};


int number_of_bulidins (){
    return sizeof(builtin_str)/sizeof(char*);
}


int Miku_cd(char** args){
    if(args[1] == NULL ){
        printf("please enter a dirctory ");
    }
    else {
        if(chdir(args[1]) != 0){
              perror("Miku_shell"); //返回值:成功返回0 ,失败返回-1
        }
    }
    
    return 1;
}


int Miku_help(char **args){
    int i;
    printf("*********************Miku Shell*********************\n");
    printf("The bulidin functions are as follows\n");

    for (i = 0; i < number_of_bulidins(); i++) {
      printf("  %s\n", builtin_str[i]);
    }

    return 1;
}


int Miku_exit (char **args){
    return 0;
}


int Miku_info(char **args){
    printf("“COMP2211 Simplified Shell by Luo Ruidi sc17rl@leeds.ac.uk.”\n");
    return 1;
}



// *************系统调用,  //


int Miku_launch(char** args){
    
    pid_t pid ;  //进程 ID
  
    int status;
    
    pid = fork();  /*
                    在父进程中返回 >0
                    在子进程中返回  0
                    错误返回。     <0   由其返回值 可判断实在 父 还是在子
                    */
    if(pid < 0 ){
        perror("Miku_shell");
    }
    else if (pid == 0){
        //返回-1 表示失败
        if(  execvp(args[0], args)  == -1 )
        {
             perror("Miku_shell");
        }
    }
    else {
        do {
            waitpid(pid ,&status ,WUNTRACED);
        }while(!WIFEXITED(status) && !WIFSIGNALED(status));
    }
    
    return 1;
    
}

/*
   输入ex + 可执行文件名 + 传递的参数
 */

int Miku_Ex(char** args){
    
    pid_t pid ;
    int status;
    pid = fork();
    if(pid < 0 ){
        perror("Miku_shell");
    }
    else if (pid == 0){
        if(  execvp(args[1], args)  == -1 )
        {
             perror("Miku_shell");
        }
    }
    else {
        do {
            waitpid(pid ,&status ,WUNTRACED);
        }while(!WIFEXITED(status) && !WIFSIGNALED(status));
    }
    return 1;
    
}



/*
 
 */

int Miku_grep(char** args){
    pid_t pid ;
    int status;
    pid = fork();
    if(pid < 0 ){
        perror("Miku_shell");
    }
    else if (pid == 0){
        if(  execlp("grep","grep" ,args[1],args[2],args[3])  == -1 )
        {
             perror("Miku_shell");
        }
    }
    else {
        do {
            waitpid(pid ,&status ,WUNTRACED);
        }while(!WIFEXITED(status) && !WIFSIGNALED(status));
    }
    return 1;

}

char readmes[25] ;
int Miku_pipeline(char** args){
   int chidB ,chidC;
    int pipefd[2];
    
    //创建 管道
    if( pipe(pipefd)==-1 ){
        printf("pipe fault\n");
        return 1;
    }
    if(!(chidB =fork() ) ){
        close(pipefd[1]);  //在B中 关闭他的写pipe权限 只让他读
        close(0)  ;// 0 -> stdin
        dup2(pipefd[0], 0); //将B的读区位置 设为 管道的0 口
       
        read(pipefd[0], readmes, 25);
        char *args1[] = {readmes, NULL};
        close(pipefd[0]);
        execve(args[4],args1,NULL);
    }
    close(pipefd[0]); // 在A 主程序中
    if(!(chidC =fork() ) ){
             close(pipefd[0]);  //在C中 关闭他的读pipe权限 只让他输出
             close(1)  ;// 1 -> stdout
             dup2(pipefd[1], 1); //将C的输出位置 设为 管道的1 口
             execve(args[1],NULL,NULL);
         }
    close(pipefd[1]); // 在主程序中
    wait4(chidB, NULL, 0, NULL);
  //  printf("%s\n", "OVER!");
   

    return 1;
}




int Miku_execute(char **args){
    int i= 0 ;
    
    if(args[0] == NULL ){
        return 1;
    }
    
    for(i=0 ;i<number_of_bulidins() ;i++)
    {
        if (strcmp(args[0], builtin_str[i]) == 0 )
            return (*builtin_func[i])(args);
    }
    
   
   if( strcmp(args[0], "ex") == 0 ){

        if( strcmp(args[2], "|") == 0){
               Miku_pipeline(args);
               return 1;
           }
        else{
        return Miku_Ex(args);
        }
    }
    else if (strcmp(args[0], "mygrep") == 0 ){
        return Miku_grep(args);
    }
    
    
    return Miku_launch(args);
    
}



void Miku_loop(void){
    
    
    //全都是 指针型。目的是啥?
    char *line  ;  //读取用户输入
    char **args ; //转译 输入?
    
    int  status = 0 ; //状态显示
    
    do{
        printf("Miku_Shell> "); //打出一个提示符 告知用户输入
        line = Miku_read_line();
        args = Miku_split_line(line);
        status = Miku_execute(args);
  
        free(line);
        free(args);
    }while(status);
    

}



int main(int argc, const char * argv[]) {


    Miku_loop();
    
    return 0;
    
}

 

个人觉得macOS Mojave 应该是这个世界上最不稳定的操作系统了,今天试着跑了跑自己写的shell 结果 直接编译过程中就把我的main文件直接杀掉了,真的不知道苹果是怎么想的?自己主打的OS都不尽善尽美,你卖NM电脑? 估计以后还是会转回Windos。奉劝各位一句 要么linux 要么windos !Macos 不易久留。
最后贴出一份自己写的shell 作为备份,以后得多多注意。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <unistd.h>


#define Miku_RL_BUFFERSIZE 1024
#define Miku_SEC_BUFFER    64
#define Miku_SEC_DELIM  " \t\r\n"
// \t 的意思是 横向跳到下一制表符位置 \r 的意思是 回车 \n 的意思是回车换行

char *Miku_read_line(void)
{
    int buffersize = Miku_RL_BUFFERSIZE ;                  //空间大小
    int position  =0 ;                                  //存入buffer的位置index
    
    int c ;                                             //每次所读取的 字符! 注意是字符!不是整数
                                                        //因为之后要判断EOF 这是一个int类型

    char * buffer = malloc(sizeof(char)* buffersize );  //创建一个数组 指向空间 的指针
    
    //检查缓冲区是否创建成功
    if(!buffer){
        printf("Miku: memoery allocation wrong !");
        exit(EXIT_FAILURE);
    }
    
    while(1){
        //字符获取
        c = getchar();
        //判断终止符EOF 和 换行符?
        if(c=='"'){
            continue;
        }
        else if(c == EOF || c =='\n'){
            buffer[position] = '\0';
            return buffer ;
        }
        else{
            buffer[position]= c ;
            position++;
        }
        
        //如果超出了我们限定的数组大小。
        if( position >= buffersize ){
            //扩大数组容量
            buffersize += Miku_RL_BUFFERSIZE;
            buffer = realloc(buffer, buffersize);
            
            if(!buffer ){
                printf("Miku: memoery allocation wrong !");
                exit(EXIT_FAILURE);
            }
        }
    }
}

char **Miku_split_line( char* line ){
    
    int bufsize = Miku_SEC_BUFFER;
    int position = 0;
    char **total_sec = malloc( sizeof(char*)*bufsize );
    char *sec ;
    
    if( !total_sec ){
        printf("Miku: memoery allocation wrong !");
        exit(EXIT_FAILURE);
    }
    
    sec =strtok( line , Miku_SEC_DELIM );
    while( sec!=NULL ){
        total_sec[position] = sec ;
        position++ ;
        //容量监控
        if(position >=bufsize){
            bufsize  +=Miku_SEC_BUFFER;
            total_sec = realloc(total_sec, bufsize);
            if(total_sec==NULL){
                printf("Miku: memoery allocation wrong !");
                exit(EXIT_FAILURE);
            }
        }
        sec = strtok(NULL ,Miku_SEC_DELIM );
        // 这个地方的参数NULL 表示接着上一个被找到的 位置继续往后查找。
    }
    total_sec[position] = NULL ; //封上
    return total_sec;
}



/*        内置函数         */
int Miku_cd(char **args);
int Miku_help(char **args);
int Miku_exit(char **args);
int Miku_info(char **args);


//一个数组 其中的元素类型为 char型指针(即指向字符串首字符)
char *builtin_str[] = {
  "cd",
  "help",
  "exit",
  "info"
};

int (*builtin_func[]) (char **) = {
  &Miku_cd,
  &Miku_help,
  &Miku_exit,
  &Miku_info
};


int number_of_bulidins (){
    return sizeof(builtin_str)/sizeof(char*);
}


int Miku_cd(char** args){
    if(args[1] == NULL ){
        printf("please enter a dirctory ");
    }
    else {
        if(chdir(args[1]) != 0){
              perror("Miku_shell"); //返回值:成功返回0 ,失败返回-1
        }
    }
    
    return 1;
}


int Miku_help(char **args){
    int i;
    printf("*********************Miku Shell*********************\n");
    printf("The bulidin functions are as follows\n");

    for (i = 0; i < number_of_bulidins(); i++) {
      printf("  %s\n", builtin_str[i]);
    }

    return 1;
}


int Miku_exit (char **args){
    return 0;
}


int Miku_info(char **args){
    printf("“COMP2211 Simplified Shell by Luo Ruidi sc17rl@leeds.ac.uk.”\n");
    return 1;
}



// *************系统调用,  //


int Miku_launch(char** args){
    
    pid_t pid ;  //进程 ID
  
    int status;
    
    pid = fork();  /*
                    在父进程中返回 >0
                    在子进程中返回  0
                    错误返回。     <0   由其返回值 可判断实在 父 还是在子
                    */
    if(pid < 0 ){
        perror("Miku_shell");
    }
    else if (pid == 0){
        //返回-1 表示失败
        if(  execvp(args[0], args)  == -1 )
        {
             perror("Miku_shell");
        }
    }
    else {
        do {
            waitpid(pid ,&status ,WUNTRACED);
        }while(!WIFEXITED(status) && !WIFSIGNALED(status));
    }
    
    return 1;
    
}

/*
   输入ex + 可执行文件名 + 传递的参数
 */

int Miku_Ex(char** args){
    
    pid_t pid ;
    int status;
    pid = fork();
    if(pid < 0 ){
        perror("Miku_shell");
    }
    else if (pid == 0){
        if(  execvp(args[1], args)  == -1 )
        {
             perror("Miku_shell");
        }
    }
    else {
        do {
            waitpid(pid ,&status ,WUNTRACED);
        }while(!WIFEXITED(status) && !WIFSIGNALED(status));
    }
    return 1;
    
}



/*
 
 */

int Miku_grep(char** args){
    pid_t pid ;
    int status;
    pid = fork();
    if(pid < 0 ){
        perror("Miku_shell");
    }
    else if (pid == 0){
        if(  execlp("grep","grep" ,args[1],args[2],args[3])  == -1 )
        {
             perror("Miku_shell");
        }
    }
    else {
        do {
            waitpid(pid ,&status ,WUNTRACED);
        }while(!WIFEXITED(status) && !WIFSIGNALED(status));
    }
    return 1;

}






int Miku_execute(char **args){
    int i= 0 ;
    
    if(args[0] == NULL ){
        return 1;
    }
    
    for(i=0 ;i<number_of_bulidins() ;i++)
    {
        if (strcmp(args[0], builtin_str[i]) == 0 )
            return (*builtin_func[i])(args);
    }
    
    
    if( strcmp(args[0], "ex") == 0 ){
        return Miku_Ex(args);
    }
    else if (strcmp(args[0], "mygrep") == 0 ){
        return Miku_grep(args);
    }
    
    
    return Miku_launch(args);
    
}



void Miku_loop(void){
    
    
    //全都是 指针型。目的是啥?
    char *line  ;  //读取用户输入
    char **args ; //转译 输入?
    
    int  status = 0 ; //状态显示
    
    do{
        printf("Miku_Shell> "); //打出一个提示符 告知用户输入
        line = Miku_read_line();
        args = Miku_split_line(line);
        status = Miku_execute(args);
  
        free(line);
        free(args);
    }while(status);
    

}



int main(int argc, const char * argv[]) {


    Miku_loop();
    return 0;
    
}


/* if( c =='"' ){
           continue;
       }
       else*/

 今天的份 终于用C语言实现了 pipe!! 太难了 有时候真的觉得国内的资源太少了,什么东西查半天! 等过几天 我一定详细 整理一遍我最近搞得东西!保证 大白话讲的明明白白!

#include <stdio.h>
#include <unistd.h>
#include <string.h>

/*
 管道对于管道两端的进程而言,就是一个文件,
 但它不是普通的文件,它不属于某种文件系统,而是自立门户,单独构成一种文件系统,并且只存在于内存中
 写入的内容每次都添加在管道缓冲区的末尾,并且每次都是从缓冲区的头部读出数据。
 FILO  queue
 
 pipe 可以看作两端各有2个端口的  管子
 
 pipe(int fd[2]) ; 这个函数被调用成功后会直接返回两个数值 fd【0】->r  fd【1】->w   文件描述符
 之后在进程中可以通过。open和close 达到控制 pipe的输入和输出权限 控制。
 比如close(fd【0】) 在父进程中调用的话  关闭管道读端口

 */
void pipeline (char *args ){
    
}


int main(int argc, const char * argv[]) {
   

    char readmes[25] ;
    int fd[2];
    pid_t pid;
    
    //创建 管道
    if( pipe(fd)==-1 ){
        printf("pipe fault\n");
        return 1;
    }
    
    pid = fork();
    if(pid<0){
        printf("fork wrong\n");
    }
    else if(pid==0){   // 子进程
        close(fd[1]) ; //关闭子进程的 写 权限
        read(fd[0], readmes, 25);  //第一个参数表明从哪里读区 这里给的是 pipe的read端口 ((write                                         端口被我们关闭了
                                   //第二个参数 表示我们要把读出来的东西放到哪里(这里我要读一个字符串)
                                   //第三个参数 表示我们的
       // printf("%s\n",readmes);
        char *args1[] = {readmes, NULL};
        execve("./B",args1,NULL);
        close(fd[0]);            //读取完成后 关闭该端口
    }
    else{ // 父进程
        close(fd[0])  ;//关闭父进程的 读 权限
        execve("./A",NULL,NULL);
        dup2(fd[1], 1);
       // write(fd[1], args1, strlen(args1)+1 );
        close(fd[0]);
        
    }

    return 0;
}



/*
 for(int i=0 ; i<argc ; i++){
        if (  strcmp("|", argv[i]) ==0){
            flag =1;
        }
    }
  int flag =1 ;
 */

 最终全部实现了!!!!爽死了 ,今晚好好记录一下整个过程!

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <unistd.h>
#include <sys/wait.h>
#include<sys/stat.h>
#include <fcntl.h>  //O_CREAT


#define Miku_RL_BUFFERSIZE 1024
#define Miku_SEC_BUFFER    64
#define Miku_SEC_DELIM  " \t\r\n"
// \t 的意思是 横向跳到下一制表符位置 \r 的意思是 回车 \n 的意思是回车换行

char *Miku_read_line(void)
{
    int buffersize = Miku_RL_BUFFERSIZE ;                  //空间大小
    int position  =0 ;                                  //存入buffer的位置index
    
    int c ;                                             //每次所读取的 字符! 注意是字符!不是整数
                                                        //因为之后要判断EOF 这是一个int类型

    char * buffer = malloc(sizeof(char)* buffersize );  //创建一个数组 指向空间 的指针
    
    //检查缓冲区是否创建成功
    if(!buffer){
        printf("Miku: memoery allocation wrong !");
        exit(EXIT_FAILURE);
    }
    
    while(1){
        //字符获取
        c = getchar();
        //判断终止符EOF 和 换行符?
        if(c=='"'){
            continue;
        }
        else if(c == EOF || c =='\n'){
            buffer[position] = '\0';
            return buffer ;
        }
        else{
            buffer[position]= c ;
            position++;
        }
        
        //如果超出了我们限定的数组大小。
        if( position >= buffersize ){
            //扩大数组容量
            buffersize += Miku_RL_BUFFERSIZE;
            buffer = realloc(buffer, buffersize);
            
            if(!buffer ){
                printf("Miku: memoery allocation wrong !");
                exit(EXIT_FAILURE);
            }
        }
    }
}

char **Miku_split_line( char* line ){
    
    int bufsize = Miku_SEC_BUFFER;
    int position = 0;
    char **total_sec = malloc( sizeof(char*)*bufsize );
    char *sec ;
    
    if( !total_sec ){
        printf("Miku: memoery allocation wrong !");
        exit(EXIT_FAILURE);
    }
    
    sec =strtok( line , Miku_SEC_DELIM );
    while( sec!=NULL ){
        total_sec[position] = sec ;
        position++ ;
        //容量监控
        if(position >=bufsize){
            bufsize  +=Miku_SEC_BUFFER;
            total_sec = realloc(total_sec, bufsize);
            if(total_sec==NULL){
                printf("Miku: memoery allocation wrong !");
                exit(EXIT_FAILURE);
            }
        }
        sec = strtok(NULL ,Miku_SEC_DELIM );
        // 这个地方的参数NULL 表示接着上一个被找到的 位置继续往后查找。
    }
    total_sec[position] = NULL ; //封上
    return total_sec;
}



/*        内置函数         */
int Miku_cd(char **args);
int Miku_help(char **args);
int Miku_exit(char **args);
int Miku_info(char **args);


//一个数组 其中的元素类型为 char型指针(即指向字符串首字符)
char *builtin_str[] = {
  "cd",
  "help",
  "exit",
  "info"
};

int (*builtin_func[]) (char **) = {
  &Miku_cd,
  &Miku_help,
  &Miku_exit,
  &Miku_info
};


int number_of_bulidins (){
    return sizeof(builtin_str)/sizeof(char*);
}


int Miku_cd(char** args){
    if(args[1] == NULL ){
        printf("please enter a dirctory ");
    }
    else {
        if(chdir(args[1]) != 0){
              perror("Miku_shell"); //返回值:成功返回0 ,失败返回-1
        }
    }
    
    return 1;
}


int Miku_help(char **args){
    int i;
    printf("*********************Miku Shell*********************\n");
    printf("The bulidin functions are as follows\n");

    for (i = 0; i < number_of_bulidins(); i++) {
      printf("  %s\n", builtin_str[i]);
    }

    return 1;
}


int Miku_exit (char **args){
    return 0;
}


int Miku_info(char **args){
    printf("“COMP2211 Simplified Shell by Luo Ruidi sc17rl@leeds.ac.uk.”\n");
    return 1;
}



// *************系统调用,  //


int Miku_launch(char** args){
    
    pid_t pid ;  //进程 ID
  
    int status;
    
    pid = fork();  /*
                    在父进程中返回 >0
                    在子进程中返回  0
                    错误返回。     <0   由其返回值 可判断实在 父 还是在子
                    */
    if(pid < 0 ){
        perror("Miku_shell");
    }
    else if (pid == 0){
        //返回-1 表示失败
        if(  execvp(args[0], args)  == -1 )
        {
             perror("Miku_shell");
        }
    }
    else {
        do {
            waitpid(pid ,&status ,WUNTRACED);
        }while(!WIFEXITED(status) && !WIFSIGNALED(status));
    }
    
    return 1;
    
}

/*
   输入ex + 可执行文件名 + 传递的参数
 */

int Miku_Ex(char** args){
    
    pid_t pid ;
    int status;
    pid = fork();
    if(pid < 0 ){
        perror("Miku_shell");
    }
    else if (pid == 0){
        if(  execvp(args[1], args)  == -1 )
        {
             perror("Miku_shell");
        }
    }
    else {
        do {
            waitpid(pid ,&status ,WUNTRACED);
        }while(!WIFEXITED(status) && !WIFSIGNALED(status));
    }
    return 1;
    
}



/*
 
 */

int Miku_grep(char** args){
    pid_t pid ;
    int status;
    pid = fork();
    if(pid < 0 ){
        perror("Miku_shell");
    }
    else if (pid == 0){
        if(  execlp("grep","grep" ,args[1],args[2],args[3])  == -1 )
        {
             perror("Miku_shell");
        }
    }
    else {
        do {
            waitpid(pid ,&status ,WUNTRACED);
        }while(!WIFEXITED(status) && !WIFSIGNALED(status));
    }
    return 1;

}

char readmes[25] ;
int Miku_pipeline(char** args){
   int chidB ,chidC;
    int pipefd[2];
    
    //创建 管道
    if( pipe(pipefd)==-1 ){
        printf("pipe fault\n");
        return 1;
    }
    if(!(chidB =fork() ) ){
        close(pipefd[1]);  //在B中 关闭他的写pipe权限 只让他读
        close(0)  ;// 0 -> stdin
        dup2(pipefd[0], 0); //将B的读区位置 设为 管道的0 口
       
        read(pipefd[0], readmes, 25);
        char *args1[] = {readmes, NULL};
        close(pipefd[0]);
        execve(args[4],args1,NULL);
    }
    close(pipefd[0]); // 在A 主程序中
    if(!(chidC =fork() ) ){
             close(pipefd[0]);  //在C中 关闭他的读pipe权限 只让他输出
             close(1)  ;// 1 -> stdout
             dup2(pipefd[1], 1); //将C的输出位置 设为 管道的1 口
             execve(args[1],NULL,NULL);
         }
    close(pipefd[1]); // 在主程序中
    wait4(chidB, NULL, 0, NULL);
  //  printf("%s\n", "OVER!");
   

    return 1;
}

int Miku_redirection(char **args){
    int fd = open("a.txt",O_CREAT|O_RDWR|O_TRUNC, S_IRUSR|S_IWUSR);
      if(fd<0){
          printf("Open Error!\n");
          return 0;
      }
    //  write(fd, "miku", strlen("miku"));
      pid_t pid;
      pid = fork();
      if(pid<0){
             printf("fork wrong\n");
         }
      else if(pid==0){   // 子进程
         close(1)  ;// 1 -> stdout
         dup2(fd, 1); //将C的输出位置 设为 管道的1 口
         execve(args[1],NULL,NULL);
          
         }
      else{
          
      }
      close(fd);
    return 1;
}


int Miku_execute(char **args){
    int i= 0 ;
    
    if(args[0] == NULL ){
        return 1;
    }
    
    for(i=0 ;i<number_of_bulidins() ;i++)
    {
        if (strcmp(args[0], builtin_str[i]) == 0 )
            return (*builtin_func[i])(args);
    }
    
   
   if( strcmp(args[0], "ex") == 0 ){

        if( strcmp(args[2], "|") == 0){
               Miku_pipeline(args);
               return 1;
           }
        else if (strcmp(args[2], ">") == 0){
           return Miku_redirection(args);
        }
        else{
        return Miku_Ex(args);
        }
    }
    else if (strcmp(args[0], "mygrep") == 0 ){
        return Miku_grep(args);
    }
    
    
    return Miku_launch(args);
    
}



void Miku_loop(void){
    
    
    //全都是 指针型。目的是啥?
    char *line  ;  //读取用户输入
    char **args ; //转译 输入?
    
    int  status = 0 ; //状态显示
    
    do{
        printf("Miku_Shell> "); //打出一个提示符 告知用户输入
        line = Miku_read_line();
        args = Miku_split_line(line);
        status = Miku_execute(args);
  
        free(line);
        free(args);
    }while(status);
    

}



int main(int argc, const char * argv[]) {


    Miku_loop();
    
    return 0;
    
}

 

posted on 2019-10-03 18:33  ReadyLoveMiku  阅读(182)  评论(0编辑  收藏  举报