linux课程设计指导文档 联系客服

发布时间 : 星期一 文章linux课程设计指导文档更新完毕开始阅读b08d5cda7f1922791688e89f

的那个,否则会出错。--libs、--cflags中都是两个横线,

注意 ,在不同的系统下,编译命令的参数顺序可能略有不同,如: gcc 1_2.c -o 1_2`pkg-config --cflags --libs gtk+-2.0`

在某次实验的时候,就不能通过编译,提示1_2.c:1:21: 错误:gtk/gtk.h:没有那个文件或目录

但更换一下参数顺序就可以了:

gcc `pkg-config --cflags --libs gtk+-2.0`1_2.c -o 1_2

这点大家要注意,当出现问题的要善于解决,自己利用网络和资料,进行处理,多思考,多尝试。

3

第2章 问题2及相关知识

系统调用是应用程序和操作系统内核之间的功能接口,通过系统调用进程可由用户模式转入内核模式,在内核模式下完成相应的服务之后再返回到用户模式。系统调用的主要目的是使得用户可以使用操作系统提供的有关设备管理、输入/输出系统、文件系统和进程控制、通信以及存储管理等方面的功能,而不必了解系统程序的内部结构和有关硬件细节,从而起到减轻用户负担和保护系统以及提高资源利用率的作用。

2.1. Linux系统调用机制

1. 内核中系统调用的过程

在Linux系统中,系统调用是作为一种异常类型实现的,它将执行相应的机器代码指令来产生异常信号。产生中断或异常的重要效果是系统自动将用户态切换为核心态来对它进行处理。这就是说,执行系统调用异常指令时,自动地将系统切换为核心态(模式切换,mode switch),并安排异常处理程序的执行。 用户态的程序只有通过门(gate)陷入(trap)到系统内核中去(执行int指令),才能执行一些具有特权的内核函数。系统调用完成后,系统执行另一组特征指令(iret指令)将系统返回到用户态,控制权返回给进程。

Linux用来实现系统调用异常的实际指令是: int $0x80

这一指令使用中断/异常向量号128(即16进制的80)将控制权转移给内核(进行模式切换)。为达到在使用系统调用时不必用机器指令编程,在标准的C语言库中为每一系统调用提供了一段短的子程序,完成机器代码的编程工作。事实上,机器代码段非常简短。它所要做的工作只是将送给系统调用的参数加载到CPU寄存器中,接着执行int $0x80指令。然后运行系统调用,系统调用的返回值将送入CPU的一个寄存器中,标准的库子程序取得这一返回值,并将它送回用户程序。

4

下面以getuid()系统调用为例来看调用过程:

用户程序 int main() { ….. getpid(标准C库 int getuid(void) { long all) pushl êx SAVE_ALL GET_CURRENT内核例程 asmlinkage long sys_getuid16(void) {

我们可以看到其中有一些宏定义,我们可以看看这些宏的定义

(arch/i386/kernel/ entry.S ). ???

#define SAVE_ALL \\ cld; \\ pushl %es; \\ pushl %ds; \\ pushl êx; \\ pushl ?p; \\ pushl íi; \\ pushl %esi; \\

中断处理 ENTRY(system_c 5

pushl íx; \\ pushl ìx; \\ pushl ?x; \\

movl $(__USER_DS),íx; \\ movl íx,%ds; \\ movl íx,%es;

我们可以看到SAVE_ALL主要是保存寄存器信息,即现场保留.其中, movl $(__USER_DS), íx;从这一句开始是重新填充DS,ES段。

#define RESTORE_INT_REGS \\ popl ?x; \\ popl ìx; \\ popl íx; \\ popl %esi; \\ popl íi; \\ popl ?p; \\ popl êx

#define RESTORE_REGS \\ RESTORE_INT_REGS; \\ 1: popl %ds; \\ 2: popl %es;

\\

.section .fixup,\\\ 3: movl $0,(%esp); \\ jmp 1b;

\\

4: movl $0,(%esp); \\ jmp 2b;

\\

.previous;

\\

.section __ex_table,\ .align 4;

\\

.long 1b,3b; \\

6