20145325张梓靖 《信息安全系统设计基础》第12周学习总结

20145325张梓靖 《信息安全系统设计基础》第12周学习总结

代码学习

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

  • 指针数组 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)( ); 指向函数的指针,这里声明了一个指针p,该指针指向返回值是整型(即函数类型为整型)的函数。

  • 指针函数int *p(int a,float b); //返回值为指针的函数...该函数返回指向整型变量的指针即该函数的类型为int *, p和上例不同,他是函数名,上例中是指针。

  • 例子 void ( *signal( int sig, void (* handler)( int )))( int );
    1)int (*p)();
    这是一个函数指针, p所指向的函数是一个不带任何参数, 并且返回值为int的一个函数。
    2)int (*fun())();
    这个式子与上面式子的区别在于用fun()代替了p,而fun()是一个函数,所以说就可以看成是fun()这个函数执行之后,它的返回值是一个函数指针,这个函数指针(其实就是上面的p)所指向的函数是一个不带任何参数,并且返回值为int的一个函数。
    3)void (*signal(int signo, void (*handler)(int)))(int);就可以看成是signal()函数(它自己是带两个参数,一个为整型,一个为函数指针的函数),而这个signal()函数的返回值也为一个函数指针,这个函数指针指向一个带一个整型参数,并且返回值为void的一个函数。

  • exec 除启动UNIX内核本身外,exec是程序在UNIX上获得执行的唯一方法,不仅shell使用exec执行程序,而且shell和其祖先shell也会被exec调用。exec系统调用从指定程序重新初始化进程,虽然进程还在,但程序已经改变了。其中只有execve是真正意义上的系统调用,其它都是在此基础上经过包装的库函数。exec函数族的作用是根据指定的文件名找到可执行文件,并用它来取代调用进程的内容,换句话说,就是在调用进程内部执行一个可执行文件。这里的可执行文件既可以是二进制文件,也可以是任何Linux下可执行的脚本文件。

  • fock fock是创建新进程的唯一方式。fock系统调用仅通过复制指令、用户数据和系统数据段来创建从现存进程克隆的新进程,该新进程不是从程序初始化得来的,所以旧进程和新进程执行同样的指令。当调用 fock 成功后,一般子进程接着执行exec ,而父进程要么等待子进程终止,要么离开去做其他的事情。若父进程正在运行多线程,那么只有执行 fock 的那个线程会存在与子进程中,父进程中的多个线程不会受到什么影响。

  • wait pid_t wait(int *status);进程一旦调用了wait,就立即阻塞自己,由wait自动分析是否当前进程的某个子进程已经退出,如果让它找到了这样一个已经变成僵尸的子进程,wait就会收集这个子进程的信息,并把它彻底销毁后返回;如果没有找到这样一个子进程,wait就会一直阻塞在这里,直到有一个出现为止。参数status用来保存被收集进程退出时的一些状态,它是一个指向int类型的指针。但如果我们对这个子进程是如何死掉的毫不在意,只想把这个僵尸进程消灭掉,,我们就可以设定这个参数为NULL,就象下面这样:
    pid = wait(NULL);
    如果成功,wait会返回被收集的子进程的进程ID,如果调用进程没有子进程,调用就会失败,此时wait返回-1,同时errno被置为ECHILD。

  • waitpid pid_t waitpid(pid_t pid,int *status,int options) 从本质上讲,系统调用waitpid和wait的作用是完全相同的,但waitpid多出了两个可由用户控制的参数pid和options,从而为编程提供了另一种更灵活的方式。

  • pipe int pipe(int fd[2]);pipe用于创建管道,并将代表管道读端和写端的打开文件描述符分别放入fd[0],fd[1]输出参数中;fd是进程调用pipe时最小的两个可用打开文件描述符;写入到fd[1]中的数据,可以从fd[0]中读出;从fd[0]中读出的数据顺序与写入fd[1]数据顺序相同。返回值为0表示,管道创建成功;返回-1表示,管道创建失败,errno中有失败原因。当读pipe文件时,如果没有数据可读read将会阻塞。直到有数据为止。然而如果进程没有打开的pipe文件来进行写操作时(即所有用于写的pipe文件符都被关闭),read将会返回0而退出阻塞。

  • fifo FIFO不同于pipe的地方:
    1)FIFO可以看作高级的管道。它突破了pipe的限制(只能用于同源进程之间的通信),可以给任意进程之间建立通信连接;
    2)FIFO是一个实际存在于磁盘中的文件;而pipe是由进程创建的,依赖于进程的存活期。
    可以调用mkfifo函数来创建一个FIFO文件。因为它本质上是一个文件,所以进程用open函数来打开一个FIFO,并在打开时指定文件操作模式(只读,只写还是读写)。之后用read(write)函数来读(写)FIFO。当一个进程以只写方式打开FIFO文件,另一个进程以只读方式打开同一个FIFO文件,这样就建立了两个进程之间的通信管道。

  • signalSIG_DFL代表执行系统默认操作,其实对于大多数信号的系统默认动作时终止该进程。这与不写此处理函数是一样的。SIG_IGN,那么信号会被忽略。

    • SIGINT信号:可以由CTRL +C 或者是DELETE产生
    • SIGQUIT信号:CTRL +\组合键时产生
    • 系统的信号我们可以再终端键入 kill -l查看(共64个)。其实这些信号是系统定义的宏
  • access int access(const char * pathname, int mode);access()会检查是否可以读/写某一已存在的文件。参数mode有几种情况组合, R_OK,W_OK,X_OK 和F_OK。R_OK,W_OK与X_OK用来检查文件是否具有读取、写入和执行的权限。F_OK则是用来判断该文件是否存在。

  • buf void *memset(void *s, int ch, size_t n);将s所指向的某一块内存中的前n个 字节的内容全部设置为ch指定的ASCII值, 第一个值为指定的内存地址,块的大小由第三个参数指定,这个函数通常为新申请的内存做初始化工作, 其返回值为指向s的指针。

  • sigaction int sigaction(int signum,const struct sigaction *act,struct sigaction *oldact);sigaction会根据参数signum指定的信号编号来设置该信号的处理函数。参数signum可以是SIGKILL和SIGSTOP以外的任何信号。如果参数act不是空指针,则为signum设置新的信号处理函数;如果oldact不是空指针,则旧的信号处理函数将被存储在oldact中。sa_mask 用来设置在处理该信号时暂时将sa_mask 指定的信号集搁置。

  • sigemptyset sigemptyset用来将参数set信号集初始化并清空。

  • sigaddsetsigaddset()用来将参数signum 代表的信号加入至参数set 信号集里。

学习进度条

代码行数(新增/累积) 博客量(新增/累积) 学习时间(新增/累积) 重要成长
目标 3500行 25篇 300小时
第一周 70/70 2/2 22/22
第二周 150/220 1/3 23/45
第三周 160/380 1/4 25/70
第五周 250/630 1/5 30/100
第六周 25/655 1/6 27/127
第七周 30/685 2/8 25/152
第八周 0/685 2/10 20/172
第九周 61/685 2/12 22/194
第十周 414/1099 3/15 20/214
第十一周 417/1516 2/17 21/235
第十二周 0/1516 2/19 20/255

参考资料

posted @ 2016-12-04 23:17  20145325张梓靖  阅读(207)  评论(1编辑  收藏  举报