zoukankan      html  css  js  c++  java
  • 20155339 第七周加分项目 mybash的实现

    mybash的实现

    要求

    • 使用fork,exec,wait实现mybash
    • 写出伪代码,产品代码和测试代码
    • 发表知识理解,实现过程和问题解决的博客(包含代码托管链接)

    学习相关知识

    fork函数

    • 查看帮助文档可以知道fork函数的头文件,函数原型,以及函数的功能等,如下图

    • fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程,也就是两个进程可以做完全相同的事,但如果初始参数或者传入的变量不同,两个进程也可以做不同的事。

    • 一个进程调用fork()函数后,系统先给新的进程分配资源。

    • fork调用的一个奇妙之处就是它仅仅被调用一次,却能够返回两次,它可能有三种不同的返回值。
      (1)在父进程中,fork返回新创建子进程的进程ID;
      (2)在子进程中,fork返回0;
      (3)如果出现错误,fork返回一个负值。

    • 我们可以通过fork返回的值来判断当前进程是子进程还是父进程。
      练习代码:

    
    #include <unistd.h>  
    #include <stdio.h>   
    int main ()   
    {   
    	    pid_t fpid; //fpid表示fork函数返回的值  
    		    int count=0;  
    			    fpid=fork();   
    				    if (fpid < 0)   
    						        printf("error in fork!");   
    					    else if (fpid == 0) {  
    							        printf("i am the child process, my process id is %d
    ",getpid());   
    									        printf("我是子进程
    ");//  
    											        count++;  
    													    }  
    						    else {  
    								        printf("i am the parent process, my process id is %d
    ",getpid());   
    										        printf("我是父进程
    ");  
    												        count++;  
    														    }  
    							    printf("统计结果是: %d
    ",count);  
    								    return 0;  
    }  
    
    

    运行结果:

    • 问题:为什么count值没有受到影响呢?
    • 解决:因为在创建了新进程之后,所有变量都存在不同的地址中,不是共用的,所有各有各的增减变化,互不影响。

    exec函数族

    • 帮助文档

    • exec函数族提供了一个在进程中启动另一个程序执行的方法。

    • 以根据指定的文件名或目录名找到可执行文件,并用它来取代原调用进程的数据段、代码段和堆栈段。

    • 可执行文件既可以是二进制文件,也可以是Linux下任何可执行脚本文件。

    • 在该函数族中使用execl、execv、execlp、execvp函数使执行码重生时,Shell进程会将所有环境变量复制给生成的新进程;而使用execle、execve时新进程不继承任何Shell进程的环境变量,而由envp[]数组自行设置环境变量。

    • 练习代码,实现ls

    #include<unistd.h>
    main()
    {
    	char *argv[ ]={"ls", NULL};
    	char *envp[ ]={"PATH=/bin", NULL};
    	execve("/bin/ls", argv, envp);
    }
    
    
    • 运行结果

    wait函数

    • wait()会暂时停止现在进程的执行,直到有信号来到或子进程结束。假如在调用wait()时子进程已结束,则wait()会立即返回子进程结束状态值。
    • waitpid提供了一个 wait的非阻塞版本,有时希望取得一个子进程的状态, 但不想进程阻塞。

    mybash实现

    • 伪代码:
    
    while(1)
    {
        输出用户的ID,等数据;  
        用户输入命令;  
        将命令分割;
        调用fork;
        调用exec函数;
    }
    
    
    • 产品代码:
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <pwd.h>
    #include <sys/wait.h>
    #define N 100
    #define order_length 128
    #define order_num 64
    #define empty 0
    #define chars 1
    void main()
    { 
       while(1) {
    	struct passwd *my_info;
    	char path[N];
    	my_info = getpwuid(getuid());
    	getcwd(path, sizeof(path));
    	printf("[%s@%s]$ ", my_info->pw_name, path);
    
    	char str[N];
    	char a[N];
    	char *argv[N]={NULL};
    	char *envp[]={0,NULL};
            int i,j = 0, flag=1;
    	fgets(str,N,stdin);
    	str[N - 1] = '';
    	if(feof(stdin))
            {
                printf("error");
                exit(0);
            }
    	for(i=0;str[i]!=''&&i<N&&j<N;i++) {
          	if(str[i] == ' ' || str[i] == '
    ') {
              flag=1;
              str[i] = '';
          }
          else if(flag==1) {
              argv[j++] = &str[i];
              flag=0;
          }
         }
         if(fork() != 0) wait(NULL);
            else {
    	execvp(argv[0], argv);
       	perror("execlp error");
       	exit(0);
         }
     }
    }
    
    
    • 测试结果:

    遇到的问题

    • 问题一:对于用户的信息直接输出的话代码的适用性就不高,那怎么获取用户的信息呢?
    • 解决:上网查询,知道了可以通过getpwuid函数获得用户的数据,该函数是通过用户的uid查找用户的passwd数据。参考链接在下方给出。
    • 问题二:对于输入的信息,怎么进行分割?
    • 解决:刚开始直接通过一个数组获得了命令,再将原数组直接给了execvp的第二个参数,失败,再次研究,决定将用户输入的数组通过空格分割给argv数组,没分割就加上一个'',一个空格之后argv的数组下标加一,也就是将命令存在argv[0]中,参数存在argv[1]以及其之后,这样就可以使用execvp函数了。
    • 问题三,在mybash中执行完./fork之后,Ctrl+C。就会直接退出mybash。
    • 未能解决。

    参考资料

  • 相关阅读:
    电力企业信息化建设方案之调度信息报送系统
    HP QC IE11不支持( win7 64位 无法安装)解决方法
    ajax传递list集合
    mysql主从配置
    js动态获取地址栏后的参数
    html页面保存数的两种方式
    微信开发之八 页面获取周围beacon设备
    最好的时光在路上,最美的风景在远方
    【摄影】田子坊
    【前端统计图】echarts实现简单柱状图
  • 原文地址:https://www.cnblogs.com/pingcpingcuo/p/8011269.html
Copyright © 2011-2022 走看看