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 |