20145317《信息安全系统设计基础》第11周学习总结2
20145317《信息安全系统设计基础》第11周学习总结2
教材学习内容总结
8.3 系统调用错误处理
- 错误报告函数
-
错误包装函数
8.4 进程控制
8.4.1 获取进程ID
- 每个进程都有一个唯一的正数(非零)进程ID(PID)
getpid
函数返回调用进程的PID-
getppid
返回它父进程的PID(创建调用进程的进程)8.4.2 创建和终止进程
- 进程的三种状态——运行、停止和终止
- 进程会因为三种原因终止进程:收到信号,该信号默认终止进程;从主程序返回;调用exit函数
- 父进程通过调用fork创建一个新的运行子进程:父进程与子进程有相同(但是独立的)地址空间,有相同的文件藐视符集合
-
fork
调用一次返回两次、并发执行、相同的但是独立的地址空间、共享文件8.4.3 回收子进程
- 回收:当一个进程终止时,内核并不立即把它从系统中清除。相反,进程被保持在一种已终止的状态中,直到被它的父进程回收
- 僵死进程:一个终止了但是还未被回收的进程称为僵死进程,仍然消耗系统的存储器资源
- 回收子进程的两种方法:1,内核的init进程 2,父进程waitpid函数
- 如果父进程没有回收它的僵死子进程就终止了,那么内核就会安排init进城来回收它们。init进程的PID为1,并且是在系统初始化时创建的
- 一个进程可以通过调用waitpid函数来等待它的子进程终止或停止
-
wait(&status)函数,等价于调用wait(-1,&status,0)
8.4.4 让进程休眠
- sleep函数将一个进程挂起一段指定的时间
-
pause函数让调用函数休眠,直到该进程收到一个信号
8.4.5 加载并运行程序
execve
函数在当前进程的上下文中加载并运行一个新程序execve
调用一次且不返回-
getenv
函数在环境数组中搜索字符串“name=value”,找到返回指向value
的指针,否则返回NULL8.4.6 利用fork和execve运行程序
8.5 信号
- unix信号,它允许进程中断其他进程
-
低层的硬件异常是由内核异常处理程序处理的,正常情况下,对用户进程而言是不可见的。信号提供了一种机制,通知用户进程发生了这些异常
8.5.1 信号术语
- 传送一个信号的步骤:发送信号、接收信号
- 发送信号:内核通过更新目的进程中上下文中的某个状态,发送一个信号给目的进程。发送信号有两个原因:1)内核检测到一个系统事件; 2)一个进程调用kill函数,显式地要求内核发送一个信号给目的进程
- 一个进程可以给自己发送信号
- 接收信号:目的进程就接收了信号。进程可以忽略这个信号,终止或者通过执行信号处理程序捕获这个信号
-
一种类型的信号只能有一种待处理信号
8.5.2 发送信号
- 进程组:每个进程都只属于一个进程组,进程组是由一个进程组ID来标识的
- 进程可以通过
setpgid
函数返回当前进程的进程组ID - 默认的,一个子进程和它的父进程同属于一个进程组
/bin/kill
程序可以向另外的进程发送任意的信号- 在任何时刻,至多只有一个前台作业和0个或多个后台作业
- 外壳为每个作业创建一个独立的进程组,一个作业对应一个进程组
- 进程通过调用
kill
函数发送信号给其他进程(包括自己) - 进程通过调用
alarm
函数向他自己发送SIGALRM信号 -
alarm
函数安排内核在secs秒内发送一个SIGALRM信号给调用进程8.5.3 接收信号
- 进程可以通过使用signal函数来修改和信号相关的默认行为
-
SIGSTOP和SIGKILL,它们的默认行为不能被修改
8.5.4 信号处理问题
-
当一个程序捕获多个信号时,有一些问题:待处理信号不会排队等待、待处理信号被阻塞、系统调用被中断
8.5.5 可移植的信号处理
- 目的是为了统一同一信号在不通系统中的语义
-
sigaction函数,或者是它的包装函数Signal函数
8.5.6 显式地阻塞和取消阻塞
- 应用程序可以使用
sigprocmask
函数显式地阻塞和取消阻塞选择的信号 -
sigprocmask
函数改变当前已阻塞信号的集合8.5.7 同步流以避免讨厌的并发错误
8.6 非本地跳转
- c语言提供了一种用户级异常控制流形式,称为本地跳转
- 通过setjmp和longjmp函数来提供
- setjmp函数只被调用一次,但返回多次:一次是当第一次调用setjmp,而调用环境保存在缓冲区env中时,一次是为每个相应的longjmp调用
- longjmp只调用一次,但从不返回
- 非本地跳转的一个重要应用就是允许从一个深层嵌套的函数调用中立即返回,通常是由检测到某个错误情况引起的
-
非本地跳转的另一个重要应用是使一个信号处理程序分支到一个特殊的代码位置,而不是返回到达中断了的指令位置
8.7 操作进程的工具
-
Linux系统提供监控和操作进程的工具:打印一个正在运行的程序和它的子进程调用的每个系统调用的轨迹(STRACE)、列出当前系统中包括僵死进程的进程(PS)、打印出关于当前进程资源使用的信息(TOP)、显示进程的存储器映射(PMAP)、虚拟文件系统(/proc)
数组指针、指针数组、函数指针、指针函数的区别
- 指针数组(char *a[4]):定义了一个数组,而它的每个元素的类型是一个指向字符/字符串的指针
- 数组指针:(char (*a)[4]):表示一个指向“一个有4个字符类型元素的数组”的指针
- 函数指针(int (*ptr)(int x, int y)):函数指针是指向函数的指针变量。
-
指针函数(int *p(int a,float b)): 返回值为指针的函数,p为函数名,
int *
为函数类型管道和I/O重定向
管道pipe函数
- 无名管道为建立管道的进程及其子孙提供一条以比特流方式传送消息的通信管道
- 该管道在逻辑上被看作管道文件,在物理上则由文件系统的高速缓冲区构成,而很少启动外设
- 发送进程利用文件系统的系统调用write(fd[1],buf,size),把buf种的长度为size字符的消息送入管道入口fd[1],接收进程则使用系统调用read(fd[0],buf,size)从管道出口fd[0]出口读出size字符的消息置入buf中
- 这里,管道按FIFO(先进先出)方式传送消息,且只能单向传送消息
-
利用UNIX提供的系统调用pipe,可建立一条同步通信管道。其格式为:
int fd[2];pipe(fd);
这里,fd[1]为写入端,fd[0]为读出端I/O重定向dup,dup2
- dup和dup2也是两个非常有用的调用,它们的作用都是用来复制一个文件的描述符
- 它们经常用来重定向进程的stdin、stdout和stderr
- 利用函数dup,可以复制一个描述符,这两个描述符共享同一个数据结构
- dup2函数跟dup函数相似,但dup2函数允许调用者规定一个有效描述符和目标描述符的id。dup2函数成功返回时,目标描述符(dup2函数的第二个参数)将变成源描述符(dup2函数的第一个参数)的复制品,换句话说,两个文件描述符现在都指向同一个文件,并且是函数第一个参数指向的文件
本周代码托管截图
https://git.oschina.net/717py/py11/tree/master
学习进度条
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
---|---|---|---|---|
目标 | 5000行 | 30篇 | 400小时 | |
第一周 | 0/0 | 1/2 | 25/30 | 学习Linux指令 |
第二周 | 50/50 | 1/3 | 25/55 | Linux系统下的开发环境 |
第三周 | 20/70 | 1/4 | 25/80 | 信息的表示和处理 |
第五周 | 20/90 | 1/5 | 30/110 | 程序的机器级表示 |
第六周 | 20/110 | 1/6 | 30/140 | 处理器体系结构 |
第七周 | 20/130 | 1/7 | 30/170 | 存储器层次结构 |
第八周 | 0/130 | 2/9 | 10/180 | 期中复习 |
第九周 | 48/178 | 2/11 | 10/190 | 系统级I/O、错误处理 |
第十周 | 539/717 | 2/13 | 10/200 | 系统调用学习 |
第十一周 | 429/1146 | 2/15 | 10/210 | 异常控制流 |