标签:
【学习时间:8h】
【学习内容:《深入理解计算机系统》第八章 】
8.1节(主要涉及异常的入门级介绍)
【注:异常表,其条目k中包含着异常k的处理程序的地址。其中,异常表的起始地址放在异常表基址寄存器中,而异常号是异常表中的索引,相当于偏移地址】
系统调用 linux提供上百种系统调用,每种都有对应的整数号(即内核跳转表中的偏移量);在IA32系统上,系统调用通过一条int n指令提供
举例说明
【以hello程序为例】
int main()
{
write(1,"hello world\n",13);//用系统调用来写write函数
exir(0);
}
write函数第一个参数是将输出发送到stdout,第二个是要写的字节序,第三个是字节序列长度(算上,和换行符是12个;然而字符串结尾的时候还会有结束符\0)。
【针对write函数的系统调用】
movl $4,%eax//write函数的编号
movl $1,%ebx//以下是设置参数
movl $string,%ecx
movl $len,%edx
int $0x80//使用int来执行系统调用(系统调用的异常号是128)
进程计数器(PC)中的每一个值都唯一地对应于包含在程序的可执行目标文件中的指令,或者是包含在运行时动态链接的到程序的共享对象中的指令。这个PC值的序列叫做逻辑控制流。
补充:进程是轮流使用处理器的;每个进程执行它的流的一部分然后被挂起,其他进程执行。
对于一个运行在其中一个进程上下文中的程序而言,它看上去就像是唯一地占用了处理器(只不过如果精确测量的话,会发现对于一个进程来说,它在执行期间好像被停顿了若干个很短的时间)。
创建和终止进程
父进程通过调用fork函数来创建一个新的运行子进程
#include <sys/types.h>
#include <unistd.h>
pid_t fork(void);//子进程返回0;父进程返回子进程的PID;如果出错,则为-1
引入:一个进程可以通过调用waitpid函数来等待它的子进程终止或者停止
#include<sys/types.h>
#incldue<sys/wait.h>
pid_t waitpid(pid_t pid,int *status,int options);//如果成功,返回子进程的PID,如果为WNOHANG,则为0,其他错误则为-1
说明:默认地,即当options=0的时候,waitpid挂起调用进程的执行,直到它的等待集合中的一个子进程终止。如果等待集合中的一个进程在刚调用的时候就已经终止了,那么waitpid就立即返回。以上两种情况都会使得waitpid函数返回已经终止的子进程的PID,并且去除该进程。
应用举例
#include "csapp.h"
#define N 2
int main()
{
int status,i;
pid_t pid;
for(i =0;i<N;i++)
if((pid = fork())==0)
exit(100+i);
while((pid = waitpid(-1,&status,0))>0)
{
if(WIFEXITED(status))
printf("child %d terminated normally with exit status = %d\n",pid,WEXITSTATUS(status));
else
printf("child %d terminated abnormally\n",pid);
}
if(errno != ECHILD)
unix_error("waitpid error");
exit(0);
}
函数:
#include<unistd.h>
int execve(const char *filename,const char *argv[],const char *envp[]);//加载并运行可执行目标文件,如果成功则无返回值,如果不成功则返回-1
函数:setjmp,longjmp
int setjmp(imp_buf env);返回0
int sigsetjmp(sigjmp_buf env,int savesigs);
void longjmp(jmp_buf env,int retval);
void siglongjmp(sigjmp_buf env,int retval);
考虑三个具有下述起始和结束时间的进程: A(进程) 0(起始时间) 2(结束时间)
B(进程) 1(起始时间) 4(结束时间)
C(进程) 3(起始时间) 5(结束时间)
问:进程两两之间是否属于并发?
【A&C:不属于;B&C:属于;A&B:属于】
列出下面的程序所有可能的序列:
int main()
{
if(Fork() == 0)
{
printf("a");
fflush(stdout);
}
else
{
printf("b");
fflush(stdout);
waitpid(-1,NULL,0);
}
printf("c");
fflush(stdout);
exit(0);
}
【输出序列可能是:acbc,abcc,bacc,bcac】
int main()
{
int status;
pid_t pid;
printf("Hello\n");
pid = fork();
printf("%d\n",!pid);
if(pid != 0)
{
if(waitpid(-1,&status,0)>0)
{
if(WIFEXITED(status)!=0)
{
printf("%d\n",WEXITSTATUS(status));
}
}
}
printf("Bye\n");
exit(2);
}
解释:首先父进程运行,输出“Hello”,然后输出!pid也就是0——>在if中,因为创建的子进程还没有终止,所以waitpid函数被阻塞,然后切换到子进程——>子进程输出1,以及Bye,然后结束——>父进程的waitpid函数被执行,然后输出子进程的退出状态
本章内容较多,而且有些内容是需要经过不止一遍的推敲之后才可以逐渐想清楚;同时,因为涉及到对一些基本电脑动作的分解,又含有很多“陌生”的代码,因而对我来说,本章的内容还是比较具有挑战性的。
然而,让我感到欣慰的是,通过请教其他同学,我发现自己对代码的理解能力有了很大提高;同时,因为代码理解程度提高,我对本章内容的把握也得到了提高。
标签:
原文地址:http://www.cnblogs.com/shadow135211/p/4986767.html