转载:http://www.cnblogs.com/mydomain/category/262673.html
为找工作准备的~
1,几种进程间的通信方式
# 管道( pipe ):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。
# 有名管道 (named pipe) : 有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信。
# 信号量( semophore ) : 信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。
# 消息队列( message queue ) : 消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。
# 信号 ( sinal ) : 信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。
# 共享内存( shared memory ) :共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号两,配合使用,来实现进程间的同步和通信。
# 套接字( socket ) : 套解口也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同及其间的进程通信。
2,进程同步与互斥
图比较多,参看操作系统原理
3,内核态与用户态
当一个任务(进程)执行系统调用而执行内核代码时,称进程处于内核内核态,此时处理器处于特权级最高的(0级)内核代码中执行,当进程处于内核态时,执行的内核代码会使用当前进程的内核栈,每个进程都有自己的内核栈。当进程执行用户代码时,称其处于用户态,此时处理器在特权级最低的(3级)用户代码中运行。
当正在执行用户程序而突然被中断程序中断时,此时用户程序也可以象征性地称为处于进程的内核态,因为中断处理程序将使用当前进程的内核栈。这与处于内核态的进程的状态有些类似。内核态与用户态是操作系统的两种运行级别,跟intel cpu没有必然的联系,intel cpu提供Ring0-Ring3三种级别的运行模式,Ring0级别最高,Ring3最低。
Linux使用了Ring3级别运行用户态,Ring0作为内核态,没有使用Ring1和Ring2。Ring3状态不能访问Ring0的地址空间,包括代码和数据。Linux进程的4GB地址空间,3G-4G部分大家是共享的,是内核态的地址空间,这里存放在整个内核的代码和所有的内核模块,以及内核所维护的数据。用户运行一个程序,该程序所创建的进程开始是运行在用户态的,如果要执行文件操作,网络数据发送等操作,必须通过write,send等系统调用,这些系统调用会调用内核中的代码来完成操作,这时,必须切换到Ring0,然后进入3GB-4GB中的内核地址空间去执行这些代码完成操作,完成后,切换回Ring3,回到用户态。这样,用户态的程序就不能随意操作内核地址空间,具有一定的安全保护作用。
保护模式,通过内存页表操作等机制,保证进程间的地址空间不会互相冲突,一个进程的操作不会修改另一个进程的地址空间中的数据。在内核态下,CPU可执行任何指令,在用户态下CPU只能执行非特权指令。当CPU处于内核态,可以随意进入用户态;而当CPU处于用户态,只能通过中断的方式进入内核态。一般程序一开始都是运行于用户态,当程序需要使用系统资源时,就必须通过调用软中断进入内核态.
使用nm查看用户态程序的符号表内容
使用System.map(内核符号表)查看内核符号表内容
1) 测试程序中打印用户态函数地址,并调用系统调用(在内核中打印系统调用函数地址),用"用户态符号表"和"内核态符号表"示例说明内核态和用户态地址空间的差异
2) 说明内核态地址映射ioremap();用户态地址映射mmap()
4,系统调用
在系统中真正被所有进程都使用的内核通信方式是系统调用。例如当进程请求内核服务时,就使用的是系统调用。一般情况下,进程是不能够存取系统内核的。它不 能存取内核使用的内存段,也不能调用内核函数,CPU的硬件结构保证了这一点。只有系统调用是一个例外。进程使用寄存器中适当的值跳转到内核中事先定义好 的代码中执行,(当然,这些代码是只读的)。在Intel结构的计算机中,这是由中断0x80实现的。
进程可以跳转到的内核中的位置叫做system_call。在此位置的过程检查系统调用号,它将告诉内核进程请求的服务是什么。然后,它再查找系统调用表sys_call_table,找到希望调用的内核函数的地址,并调用此函数,最后返回。
所以,如果希望改变一个系统调用的函数,需要做的是编写一个自己的函数,然后改变sys_call_table中的指针指向该函数,最后再使用cleanup_module将系统调用表恢复到原来的状态