zoukankan      html  css  js  c++  java
  • 2017-2018-1 20155203 《信息安全系统设计基础》第六周学习总结

    教材学习内容总结

    fork()

    • 计算机程序设计中的分叉函数。返回值: 若成功调用一次则返回两个值,子进程返回0,父进程返回子进程标记;否则,出错返回-1。
      fork函数将运行着的程序分成2个(几乎)完全一样的进程,每个进程都启动一个从代码的同一位置开始执行的线程。这两个进程中的线程继续执行,就像是两个用户同时启动了该应用程序的两个副本。
    mybash 版本一
    
    #include <errno.h>
     #include <stdio.h>
     #include <stdlib.h>
     char command[256];
     void main()
     {
      int rtn; /*子进程的返回数值*/
      while(1) {
          
          printf( ">" );
          gets( command, 256, stdin );
          command[strlen(command)-1] = 0;
          if ( fork() == 0 ) {
             execlp( command, NULL );
             
             perror( command );
             exit( errno );
          }
          else {
             wait ( &rtn );
             printf( " child process return %d
    ", rtn );
          }
      }
    }
    

    这个版本不能得到正确结果,会打印错误提示 ,但是可以根据运行结果的内容发现,fork()的返回值有两个,一个是0代表生成的子程序,还有一个代表的父程序。

    exec( )函数族

    • 在Linux中要使用exec函数族。系统调用execve()对当前进程进行替换,替换者为一个指定的程序,其参数包括文件名(filename)、参数列表(argv)以及环境变量(envp)。exec函数族当然不止一个,但它们大致相同,在 Linux中,它们分别是:execl,execlp,execle,execv,execve和execvp,可以通过manexec命令来了解它们的具体情况。
    • 在这个函数族的函数使用的过程中主要是注意字符串数组的存放,目前看来所有的程序问题主要集中在这一部分,在这里先贴一个在网上查到的输入代码,之后再仔细研究
     numargs=0;
      while(numargs<MAXARGS){
       printf("Arg[%d]?",numargs);
       if(fgets(argbuf,ARGLEN,stdin)&&*argbuf!='
    ')
         arglist[numargs++]=makestring(argbuf);
       else{
        if(numargs>0){
          arglist[numargs]=NULL;
          execute(arglist);
          numargs=0;
        }
       }
      }
    

    wait()

    • wait(等待子进程中断或结束)
      相关函数 waitpid,fork
      表头文件
    #include<sys/types.h> 
    #include<sys/wait.h>
    pid_t wait (int * status);
    
    • 函数说明

    wait()会暂时停止目前进程的执行,直到有信号来到或子进程结
    束。如果在调用wait()时子进程已经结束,则wait()会立即返
    回子进程结束状态值。子进程的结束状态值会由参数status 返回,
    而子进程的进程识别码也会一快返回。如果不在意结束状态值,则
    参数status 可以设成NULL。子进程的结束状态值请参考waitpid()。
    返回值
    如果执行成功则返回子进程识别码(PID),如果有错误发生则返回
    -1。失败原因存于errno 中。

    waitpid()

    waitpid()会暂时停止目前进程的执行,直到有信号来到或子进程结束。waitpid的返回值比wait稍微复杂一些,一共有3种情况:

    1.当正常返回的时候,waitpid返回收集到的子进程的进程ID;
    2.如果设置了选项WNOHANG,而调用中waitpid发现没有已退出的子进程可收集,则返回0;
    3.如果调用中出错,则返回-1,这时errno会被设置成相应的值以指示错误所在;
    当pid所指示的子进程不存在,或此进程存在,但不是调用进程的子进程,waitpid就会出错返回,这时errno被设置为ECHILD;
    

    exit

    • exit()通常是用在子程序中用来终结程序用的,使用后程序自动结束,跳回操作系统。
    • exit(0) 表示程序正常退出,exit⑴/exit(-1)表示程序异常退出。
    (1)exit和return 的区别: 
    
    a.exit是一个函数,有参数。exit执行完后把控制权交给系统 
    
    b.return是函数执行完后的返回。renturn执行完后把控制权交给调用函数。 
    
    (2)exit和abort的区别: 
    
    a.exit是正常终止进程 
    
    b.about是异常终止。 
    

    getpid()

    getpid是一种函数,功能是取得进程识别码,许多程序利用取到的此值来建立临时文件,以避免临时文件相同带来的问题。通过在虚拟机中运行可以看出,getpid()的返回值每次都不一样。

    getppid()

    getpid返回当前进程标识,getppid返回父进程标识。

    sleep()

    函数功能: 执行挂起一段时间;
    Sleep函数的一般形式:

    Sleep(unsigned long);//参数即为挂起时间
    

    pause()

    alarm(time);执行之后告诉内核,让内核在time秒时间之后向该进程发送一个定时信号,然后该进程捕获该信号并处理;
    pause()函数使该进程暂停让出CPU,但是该函数的暂停和前面的那个sleep函数的睡眠都是可被中断的睡眠,也就是说收到了中断信号之后再
    重新执行该进程的时候就直接执行pause()和sleep()函数之后的语句;
    可以用alarm()函数中断pause();

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <signal.h>
     
    void sig_handler(int num)
    {
        printf("receive the signal %d.
    ", num);
        alarm(2);
    }
     
    int main()
    {
        signal(SIGALRM, sig_handler);<br>
        alarm(2);<br>
        while(1){
            pause();
            printf("pause is over.
    ");
        }
        exit(0);
    }
    

    setenv

    函数说明 setenv()用来改变或增加环境变量的内容。参数name为环境变量名称字符串。参数 value则为变量内容,参数overwrite用来决定是否要改变已存在的环境变量。如果没有此环境变量则无论overwrite为何值均添加此环境变量。若环境变量存在,当overwrite不为0时,原内容会被改为参数value所指的变量内容;当overwrite为0时,则参数value会被忽略。返回值 执行成功则返回0,有错误发生时返回-1。

    unsetenv

    int unsetenv(const char *name);
    删除name的定义,即使不存在也不算出错。
    主要用于setenv()函数使用过后释放空间。

    pipe

    管道是一种把两个进程之间的标准输入和标准输出连接起来的机制,从而提供一种让多个进程间通信的方法,当进程创建管道时,每次都需要提供两个文件描述符来操作管道。中一个对管道进行写操作,另一个对管道进行读操作。对管道的读写与一般的IO系统函数一致,使用write()函数写入数据,使用read()读出数据。

    dup duo2

    dup和dup2也是两个非常有用的调用,它们的作用都是用来复制一个文件的描述符。它们经
    常用来重定向进程的stdin、stdout和stderr。这两个函数的 原形如下:

    #include <unistd.h>    
    int dup( int oldfd );    
    int dup2( int oldfd, int targetfd )
    
    利用函数dup,我们可以复制一个描述符。传给该函数一个既有的描述符,它就会返回一个新的描述符,这个新的描述符是传给它的描述符的拷贝。这意味着,这两个描述符共享同一个数据结构。需要注意的是,我们可以在调用fork之前建立一个描述符,这与调用dup建立描述符的结果是一样的,子进程也同样会收到一个复制出来的描述符。dup2函数跟dup函数相似,但dup2函数允许调用者规定一个有效描述符和目标描述符的id。dup2函数成功返回时,目标描述符(dup2函数的第二个参数)将变成源描述符(dup2函数的第一个参数)的复制品,
    

    利用教材中的内容写mybash

    • 伪代码

    int main(){
    
    //从终端读取要执行的命令
    //fork()产生子进程执行此命令
    //如果exec函数返回,表明没有正常执行命令,打印错误信息perro()
    //父进程, 等待子进程结束,并打印子进程的返回值wait(&rtn) 
    
    }
    
    • 产品代码

    #include <errno.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <limits.h>
    
    void main()
    {
    		
    	char *command[3];
    	command[0] = "ls";
    	command[1] = "-l";
    	command[2] = 0;
            
            int s,i=0;
            int rtn; 
            printf( ">" );
    	//printf("%s %s %s",command[1],command[2],command[3]);	
    	printf("%s",command[0]);
    	i=0;	
    	s=fork();
    	if ( s== 0 ) {
    	//printf("%d
    ",s);
    	execvp( command[0], command );
    	
    	//perror( command );
    	
    	exit( errno );
    	 }
    	 else {
    	
    	//printf("%d
    ",s);
    
    	wait ( &rtn );
    	
    	printf( " child process return %d
    ", rtn );
    	
    	}
    	
    	
    	}
    
    • 遇到的主要问题在于输入的字符数组无法被正常读入,或者出现段错误。
    • 解决方案:参考教材代码P526 parseline();
    • 后续修改

    参考教材第八章parseline等关于输入字符串的代码,问题得到了解决。


    注:show为 2进制可执行文件,所以显示乱码。

    代码托管

    学习进度条

    代码行数(新增/累积) 博客量(新增/累积) 学习时间(新增/累积) 重要成长
    目标 5000行 30篇 400小时
    第一周 200/200 1/1 6/6
    第三周 156/388 2/3 15/21 这周除课堂实践外,大多数都是知识性的学习内容,代码量确实太少从下周起就要抓紧了
    第四周 156/388 3/6 15/36 每天100行好难啊,不过感觉找到了学习的一些动力。在调试代码上花的时间太多,都要没时间看书了,还要继续改进
    第五周 284/ 745 1/7 15/51

    参考资料

    深入浅出---unix多进程编程之wait()和waitpid()函数
    Sleep函数的真正用意
    getenv putenv setenv和unsetenv详解

  • 相关阅读:
    魅蓝Note有几种颜色 魅蓝Note哪个颜色好看
    Android在跳转市场进行评分问题总结
    轻松学会多线程(四)——synchronized同步keyword知多少
    对于stackoverflow的中文翻译的相关问题
    HBase总结(二十)HBase经常使用shell命令具体说明
    Tiny语言执行环境TM机源码
    【IOS工具类】获得设备唯一标识(兼容IOS5,6,7)
    VMwave下Ubuntu扩展磁盘空间
    wordpress搭建后地址栏页面显示IP地址的问题
    成都Java培训机构太多,该如何选择呢?
  • 原文地址:https://www.cnblogs.com/xhwh/p/7750261.html
Copyright © 2011-2022 走看看