zoukankan      html  css  js  c++  java
  • 《信息安全系统设计基础》第11周问题总结

    第11周学习任务:

    1. 掌握系统编程和系统调用的概念
    2. 掌握系统编程错误处理的方式
    3. 掌握Unix/Linux系统级I/O:open close read write seek stat
    4. 掌握RIO
    5. 掌握I/O重定向的方法

      下面我在阅读了完成本周作业的78位同学的博客后,将同学们所遇到的的问题进行了总结,针对没有解决的问题,给出了一些自己的看法,如有不妥,还望批评指正。下面是我的具体总结,希望可以帮助同学们更好的理解系统调用。(有重复的问题,只涉及了一次)

      

    所遇问题及解决办法

       问题1描述:不是说fork函数,产生的两个线程的执行顺序是不确定的,为什么我多次执行,都是先显示父进程的,如图所示:

       解答:的确,当我们在系统上运行这个程序时,父进程先完成了他的printf语句,在另一个系统上可能正好相反;输出行的顺序根据系统不同而不同,取决于内核如何交替执行父子进程的指令,一般而言,只要是满足条件的拓扑顺序都是合法的顺序。

       问题1描述:运行sigdemo1.csigdemo2.csigdemo3.csigactdemo.c

    sigactdemo2.c是按Ctrl+c不能终止程序进行。

       5219的解决办法:sigdemo3.c中输入quit结束程序运行。其他的我直接关闭了终端.

      解答:ctrl-c 发送 SIGINT 信号给前台进程组中的所有进程,常用于终止正在运行的程序, 也就是直接停止当前执行的命令;ctrl-z 发送 SIGTSTP 信号给前台进程组中的所有进程,常用于挂起一个进程,也就是挂起当前执行的命令。所以,ctrl +z可以结束。

     问题2描述:编译运行testpp.c后出现段错误……

      5219的解决办法:她修改了代码

     

      解答:char **pp,我喜欢叫他重指针,与数组不同的是,他在声明的时候没有分配空间,所以要malloc一下。

        问题描述:wc统计子目录代码时出现如下报错,查询资料得知如果目标文件开头用通配符 *表示,则需转义。

      

       5328的解决办法:*前加即可

      解答:wc只能统计当前目录下所指定的文件类型,不能穿过文件夹。话说,直接cd进子文件夹不就好了。。

        问题描述:虚拟机崩了包括整个电脑都带不起来无法开机。只得重装系统,又因若干写入注册表的内容无法备份

       5337的解决办法:重装系统

      解答:这个问题。。很残酷,电脑都无法开机了,没办法的办法,只能重装了;virtual box可以多重载入,详见我之前的博客基于VirtualBox的多重载入,希望这能省去你重新配置虚拟机的麻烦。

       问题1描述:对于教材中信号方面的代码不太理解。

      解答:music,“如果你愿意一层一层剥开我的心”。对,抽丝剥茧,方见真谛 ,其实这些代码都不是很长,也不复杂,只要单独弄清每一个函数的意思,应用到老师的代码里就可以理解了。

      问题2描述:编译forkdemo1.c的时候出错

      5231解决办法:根据提示修改源代码,加入#include <stdio.h>重新编译即可

      解答:我编代码的时候有个习惯,就是把常用的头文件全加上,省去之后出错检查的麻烦。

       问题描述:一体机每次打开vi都会出现如下乱码,为什么呀:

      解答:会不会是不小心删了或修改了代码,毕竟testbuf2.c里就一个printf和while啊。。

       问题1描述:exec1.c中:

      - 疑问:为什么没有显示最后打印的一句?   
      5222解答:因为在系统处理器中,在执行`execvp( "ls" , arglist );`语句时,已经将最后的打印语句覆盖掉了,处理器中并没有这句打印语句。

       问题描述:教材中介绍了教材中错误处理包装函数定义在一个叫做csapp.c的文件中,他们的原型定义在一个叫做csapp.h的头文件中,所以要想正确编译课本代码应使用gcc include/csapp.c include/csapp.h src/week11/fork.c -o bin/fork,但是会产生以下错误提示:

      5224解决方案:应该是系统没有找到函数中包含的相应函数,于是我将对应的函数都注释了再编译的时候就可以了。

      

        问题描述:习题8.3:刚开始看着道题的时候,认为有4种输出序列:abcc、bacc、acbc、bcac。但是答案上只写了3个,没有bcac。

       5337的解决办法:忽略了waitpid函数。因为有waitpid,要等待子进程结束时,才会执行父进程的打印c命令。bcac是父进程都结束了,a进程还没有开始,所以不会有这种输出顺序。

      解答:有waitpid,父进程会一直等待子进程。

        问题描述:在运行argtest的时候,出现了问题。

       5326的解决办法:后来发现,应该将argtest.c和makeargv.c,还有freemakeargv.c和argv.h放在同一目录下;运行成功~

    argv文件夹中的主要程序是argtest.c

      有两种运行方法:
      第一种是用-c将所有.c的文件编译成后缀为.o的文件,然后一起编译成可执行文件。
      第二种方法是直接将所有的.c文件编译成可执行文件,运行结果是一样的。

     

     

        问题描述:

    在虚拟机中使用/proc文件系统,结果显示权限不够,如图所示:

      5216解决方法:通过最后一节内容得知,是由于输入方法不对,应该输入的是cat打印指令,再接后面的目录,如下图:

      解答:毕竟这只是一个文件,不是一个程序,不好执行,只能显示

        问题描述:

    • 课本P504的代码的第14行中的strchr是什么函数?

       5240的解决办法:char *strchr(const char* _Str,int _Val)

                  char *strchr(char* _Str,int _Ch)         

    功能:查找字符串s中首次出现字符c的位置

    说明:返回首次出现c的位置的指针,返回的地址是被查找字符串指针开始的第一个与Val相同字符的指针,如果s中不存在c则返回NULL。

     返回值:成功则返回要查找字符第一次出现的位置,失败返回NULL

        问题描述:关于pipe.c的命令顺序不同产生的运行结果不同

      • 执行命令bin/pipe man lsbin/pipe ls man的结果不一样

      • 由于pipe.c的效果等同与命令行中的|管道

       5214的解决办法:出现这个结果的原因是管道命令本身的使用规则,如下图,command1正确输出,作为command2的输入 然后comand2的输出作为,comand3的输入 ,comand3输出就会直接显示在屏幕上面了,而通过管道之后comand1,comand2的正确输出不显示在屏幕上面

      解答:如果是ls | sort的话,还真是不能注意到这个问题,深刻。

    附指针数组、数组指针、指针函数、函数指针的区别

    数组指针(也称行指针)

    定义 int (*p)[n];
    ()优先级高,首先说明p是一个指针,指向一个整型的一维数组,这个一维数组的长度是n,也可以说是p的步长。也就是说执行p+1时,p要跨过n个整型数据的长度。

    如要将二维数组赋给一指针,应这样赋值:
    int a[3][4];
    int (*p)[4]; //该语句是定义一个数组指针,指向含4个元素的一维数组。
     p=a;        //将该二维数组的首地址赋给p,也就是a[0]或&a[0][0]
     p++;       //该语句执行过后,也就是p=p+1;p跨过行a[0][]指向了行a[1][]

    所以数组指针也称指向一维数组的指针,亦称行指针。

    指针数组


    定义 int *p[n];
    []优先级高,先与p结合成为一个数组,再由int*说明这是一个整型指针数组,它有n个指针类型的数组元素。这里执行p+1时,则p指向下一个数组元素,这样赋值是错误的:p=a;因为p是个不可知的表示,只存在p[0]、p[1]、p[2]...p[n-1],而且它们分别是指针变量可以用来存放变量地址。但可以这样 *p=a; 这里*p表示指针数组第一个元素的值,a的首地址的值。
    如要将二维数组赋给一指针数组:
    int *p[3];
    int a[3][4];
    p++; //该语句表示p数组指向下一个数组元素。注:此数组每一个元素都是一个指针
    for(i=0;i<3;i++)
    p[i]=a[i]
    这里int *p[3] 表示一个一维数组内存放着三个指针变量,分别是p[0]、p[1]、p[2]
    所以要分别赋值。

    这样两者的区别就豁然开朗了,数组指针只是一个指针变量,似乎是C语言里专门用来指向二维数组的,它占有内存中一个指针的存储空间。指针数组是多个指针变量,以数组形式存在内存当中,占有多个指针的存储空间。
    还需要说明的一点就是,同时用来指向二维数组时,其引用和用数组名引用都是一样的。
    比如要表示数组中i行j列一个元素:
    *(p[i]+j)、*(*(p+i)+j)、(*(p+i))[j]、p[i][j]

    优先级:()>[]>*

     函数指针
    在C语言中,一个函数总是占用一段连续的内存区,而函数名就是该函数所占内存区的首地址.我们可以把函数的这个首地址(或称入口地址)赋予一个指针变量,使该指针变量指向该函数.然后通过指针变量就可以找到并调用这个函数.我们把这种指向函数的指针变量称为“函数指针变量”.
    函数指针变量定义的一般形式为:
    类型说明符 (*指针变量名)();
    其中“类型说明符”表示被指函数的返回值的类型.“(* 指针变量名)”表示“*”后面的变量是定义的指针变量.最后的空括号表示指针变量所指的是一个函数.
    例如:
    int (*pf)();
    表示pf是一个指向函数入口的指针变量,该函数的返回值(函数值)是整型.

    指针函数
    函数类型是指函数返回值的类型.在C语言中允许一个函数的返回值是一个指针(即地址),这种返回指针值的函数称为指针型函数.
    定义指针型函数的一般形式为:
    类型说明符 *函数名(形参表) 

    …… /*函数体*/

    其中函数名之前加了“*”号表明这是一个指针型函数,即返回值是一个指针.类型说明符表示了返回的指针值所指向的数据类型.
    如:
    int *ap(int x,int y)
    {
    ./*函数体*/
    }
    表示ap是一个返回指针值的指针型函数,它返回的指针指向一个整型变量.

     

  • 相关阅读:
    splay复杂度的证明
    splay的写法
    洛谷 P3722 [AH2017/HNOI2017]影魔
    洛谷 P4770 [NOI2018]你的名字
    清北考前刷题day3下午好
    P3043 [USACO12JAN]牛联盟Bovine Alliance(并查集)
    bzoj3252攻略(线段树+dfs序)
    清北考前刷题day2早安
    清北考前刷题day2下午好
    清北考前刷题day1下午好
  • 原文地址:https://www.cnblogs.com/nostalgia-/p/6110219.html
Copyright © 2011-2022 走看看