• 第十二周学习总结


    信息安全系统设计基础第十二周学习总结

    【学习时间:8 小时】

    【学习内容:process文件夹中的代码理解和执行、故障排除】

    一、代码理解

    1.env文件夹-environ.c代码

    #include <stdio.h>

    #include <stdlib.h>

     

    int main(void)

    {

        printf("PATH=%s ", getenv("PATH"));//getenv函数用来取得参数PATH环境变量的值,执行成功则返回该内容的指针

        setenv("PATH", "hello", 1);//见下方解释

        printf("PATH=%s ", getenv("PATH"));

    #if 0

        printf("PATH=%s ", getenv("PATH"));

        setenv("PATH", "hellohello", 0);

        printf("PATH=%s ", getenv("PATH"));

     

     

        printf("MY_VER=%s ", getenv("MY_VER"));//版本

        setenv("MY_VER", "1.1", 0);

        printf("MY_VER=%s ", getenv("MY_VER"));

    #endif

        return 0;

    }

    【setenv函数的作用?】 
    setenv用来在本次函数运行的过程中增加或者修改环境变量。当最后一个参数不为0的时候,原来的内容会被修改为第二个参数所指的内容。

    2.env文件夹-environvar.c代码

    #include <stdio.h>

    int main(void)

    {

        extern char **environ;

        int i;

        for(i = 0; environ[i] != NULL; i++)

            printf("%s ", environ[i]);

     

        return 0;

    }

    【environ变量是什么?】 该变量指向一个叫“environment”的字符串数组。包括USER(登录用户的名字),LOGNAME(与user类似),HOME(用户登录目录),LANG(地域名),PATH等

    3.pipe文件夹-consumer.c代码

    #include <stdio.h>

    #include <stdlib.h>

    #include <string.h>

    #include <fcntl.h>

    #include <limits.h>

    #include <sys/types.h>

    #include <sys/stat.h>

     

    #define FIFO_NAME "/tmp/myfifo"

    #define BUFFER_SIZE PIPE_BUF

    int main()

    {

    int pipe_fd;

    int res;

     

    int open_mode = O_RDONLY;

    char buffer[BUFFER_SIZE + 1];

    int bytes = 0;

     

    memset(buffer, 0, sizeof(buffer));

     

    printf("Process %d opeining FIFO O_RDONLY ", getpid());

    pipe_fd = open(FIFO_NAME, open_mode);

    printf("Process %d result %d ", getpid(), pipe_fd);

     

    if (pipe_fd != -1) {//open函数正常执行

        do {

            res = read(pipe_fd, buffer, BUFFER_SIZE);

            bytes += res;

        } while (res > 0);不断地从fifo文件中读取数据,知道==直到数据被读完

        close(pipe_fd);

    } else {

        exit(EXIT_FAILURE);

    }

     

    printf("Process %d finished, %d bytes read ", getpid(), bytes);

    exit(EXIT_SUCCESS);

    }

    【PIPE_BUF的值是多少?】 4096字节

    【memset函数用法?】 原型:memset(void *s,int ch,size_t n);将s中前n个字节用ch替换并返回s

    【open函数用法?】 
    open(const char *pathname,int flags);第一个参数是欲打开的文件路径字符串,第二个参数是打开方式

    【FIFONAME是什么?】 
    这里需要补充一下fifo的含义,它是一种文件类型,可以通过查看文件stat结构中的stmode成员的值来判断文件是否是FIFO文件。fifo是用来在进程中使用文件来传输数据的,也具有管道特性,可以在数据读出的时候清除数据。

    4.pipe文件夹-pipe.c代码

    #include    <stdio.h>

    #include<stdlib.h>

    #include    <unistd.h>

     

    #define oops(m,x)   //当linux系统执行代码遇到问题时,就会报告oops

    { perror(m); exit(x); }

     

    int main(int ac, char **av)

    {

        int thepipe[2], newfd,pid;             

     

        if ( ac != 3 ){//输入的命令长度不等于3

            fprintf(stderr, "usage: pipe cmd1 cmd2 ");

            exit(1);

        }

        if ( pipe( thepipe ) == -1 )    //以下是各种错误  

            oops("Cannot get a pipe", 1);

     

        if ( (pid = fork()) == -1 )        

            oops("Cannot fork", 2);

     

        if ( pid > 0 ){        

            close(thepipe[1]); 

     

            if ( dup2(thepipe[0], 0) == -1 )

                oops("could not redirect stdin",3);

     

            close(thepipe[0]); 

            execlp( av[2], av[2], NULL);

            oops(av[2], 4);

        }

     

        close(thepipe[0]);     

     

        if ( dup2(thepipe[1], 1) == -1 )

            oops("could not redirect stdout", 4);

     

        close(thepipe[1]);     

        execlp( av[1], av[1], NULL);

        oops(av[1], 5);

    }

    5.forkdemo3.c文件

    #include    <stdio.h>

    #include<stdlib.h>

    #include<unistd.h>

     

    int main()

    {

        int fork_rv;

     

        printf("Before: my pid is %d ", getpid());

     

        fork_rv = fork();       /* 创建子进程    */

     

        if ( fork_rv == -1 )        /* 出错的情况下即子进程创建失败   */

            perror("fork");

        else if ( fork_rv == 0 ){ //子进程的返回值才是0

            printf("I am the child.  my pid=%d ", getpid());

     

            exit(0);

        }

        else{//父进程执行这段代码

            printf("I am the parent. my child is %d ", fork_rv);

            exit(0);

        }

     

        return 0;

    }

    6.testbuf3.c文件

    #include <stdio.h>

     

    int main()

    {

        fprintf(stdout, "1234", 5);

        fprintf(stderr, "abcd", 4);

    }

    【关于fprintf函数】

    函数原型:int fprintf(FILE *stram,const char *format,[argument]);第一个参数是文件指针,第二是输出格式,第三个是附加参数列表。也就是说,该函数会根据指定的格式(format)向输出流(stream)中写入数据(argument)。

    二、代码执行时的问题

    1.argv,env文件夹中的代码可以正常运行。

    2.execl1执行

    在直接 gcc execl1 -o execl1.2(因为之前已经有execl可执行文件了)之后,系统提示如图。

    后来改变方法,先生成.o 文件再生成可执行文件,就可以执行代码了。

    通过网上搜索,发现出现这个错误提示是因为使用了第三方库而没有把它的.m文件添加到compile source中去,而是可能只把这些文件copy到当前文件夹里就觉得可以了;这样在直接编译链接执行的时候根本没有自动引用(网上提供的解决方法建立在专门的编写软件基础上,在target--build phases--compile source中添加.m;不过针对我们的情况,可以分步完成以保证最终生成可执行文件)。

    3.consumer执行

    开始的时候直接gcc consumer.o -o consumer仍然出现上文中的错误。后来删除consumer .o 文件之后分步编译,可以执行。

    4.producer.c函数运行

    开始的时候,提示有错误。如图。 
    后来查询了access函数,发现它的功能是确定文件或者文件夹的访问权限。如果指定的存取方式有效,则返回0;否则返回-1.其中,f_ok只是判断该文件是否存在。而整个函数需要头文件<unistd.h>。加上该头文件之后,代码可以正常编译。

    三、代码执行情况

    1.一些不停地打印的代码,sigdemo2为例的那些根本停不下来的代码

    注:无法停止时,control+c强行停止

     

    2.一些需要等待时间才能出来的代码(含有sleep)

    (1)每隔两秒的sigactdemo2.c

    (2)每隔30s的watch.sh

    3.输入什么就打印什么或执行什么

    (1)输入什么就打印什么

    (2)输入什么就执行什么

    3.没有结果(无输出,只是申请一个20字节的内存大小)

    4.发现代码的最后一句打印不出来,自行修改后得到结果

     

    由这个变为最后加上打印OUCH

     

     

    四、心得

    通过本次实践对gcc的使用有了更深的了解与掌握,同时也学会运行了一些其他格式的文件与代码,比如.sh格式的直接运行等。

    同时,对比代码与运行结果,对sleep等函数有了更深层次的感受,比如说一开始等不到结果以为代码出现问题等等(后发现有sleep函数),并且也尝试改动了代码。

  • 相关阅读:
    Eular质数筛法
    质数测试
    求树的直径
    常用排序的实现方法(数据结构)
    关于整数的整数因子和问题的若干研究(数学)
    状态压缩中常用的位运算(DP)
    舞蹈链--求精密覆盖(数据结构)
    高斯消元模板,整数(数学)
    树状数组 (数据结构)
    二叉树还原--通用类型模板类(数据结构)
  • 原文地址:https://www.cnblogs.com/shadow135211/p/5005418.html
Copyright © 2020-2023  润新知