新年快乐呀!!今天可是除夕夜!!
1、signal是对“中断”这种概念在软件层次上的模拟(所以亦称“软中断”),其中信号的发送者相当于中断源,而接收者则相当于处理器。就像在多处理器系统中一个处理器通常都能向另一个处理器发出中断请求一样,一个进程也可以向其他进程发出信号,此时信号就成了一种进程间通信的手段。
2、管道(Pipe)、信号(signal)、跟踪(Trace)进程间通信手段都只能用于父进程与子进程之间,或者两个兄弟进程之间。信号的使用虽然并未限制在父子进程之间,但发送信号时需要用到对方的pid,而一般只有父子进程之间才知道对方的pid,所以实际上还是只能用于父子进程之间。命名管道(named pipe)。
命名管道以FIFO文件的形式出现在文件系统中,所以任何进程都可以通过使用其文件名来“打开”该管道,然后进行读写。这样,管道的使用就不再局限于“近亲”之间了。从这个意义上说,命名管道是管道的推广。
如果说“命名管道”把“管道”这种原来只适用近亲的手段推广到了同一台计算机中的任意进程之间,则Socket又进一步将其推广至计算机网络中的任意进程之间。
3、进程对每个已打开文件的操作都是通过一个file数据结构进行的,只有在由同一个进程按相同模式重复打开同一文件时才共享同一个数据结构。一个管道实际上就是一个无形(只存在于内存中)的文件,对这个文件的操作要通过两个已打开文件进行,分别代表该管道的两端。虽然最初创建时一个管道的两端都在同一进程中,但是在实际使用时却总是分别在两个不同的进程(通常是父、子进程)中,所以,管道的两端不能共享同一个file数据结构,而要为之各分配一个file数据结构。实际上,创建一个管道的过程主要就是创建这么一个文件的过程。
4、用来实现管道的文件是无形的,它并不出现在磁盘或其他的文件系统存储介质上,而只存在于内存空间,其他进程也无从“打开”或访问这个文件。所以,这个所谓文件实质上只是一个用作缓冲区的内存页面,只是把它纳入了文件系统的机制,借用了文件系统的各种数据结构和操作加以管理而已。
5、在正常的情况下,每个文件都至少有一个“目录项”,代表这个文件的一个路径名;而每个目录项则只描述一个文件,在dentry数据结构中有个指针指向相应的inode结构。因此,在file数据结构中有个指针f_dentry指向所打开文件的目录项dentry数据结构,这样,从file结构开始就可以一路通到文件的inode结构。对于管道来说,由于文件是无形的,本来并不非得有个目录项不可。可是,在file数据结构中并没有直接指向相应inode结构的指针,一定要经过一个目录项中转一下才行。
6、当关闭管道的读端时,pipe_read_release()调用pipe_release(),使共享计数readers减1;而关闭管道的写端时则使writers减1。当二者都减到了0时,整个管道就完成了使命,此时应将用作缓冲区的存储页面以及pipe_inode_info数据结构释放。在常规的文件操作中,文件的inode存在于磁盘(或其他介质)上,所以在最后关闭时要将内存中的inode数据结构写回到磁盘上。但是,管道并不是常规意义上的文件,磁盘上并没有相应的索引节点,所以最后只是将分配的inode数据结构(以及dentry结构)释放了事,而并没有什么磁盘操作。这一点从用于管道的inode数据结构中的inode_operations结构指针为0可以看出。
7、中断向量表在系统空间中,每个中断向量所指向的中断向量程序也在系统空间中。然而,虽然“信号向量表”也在系统空间中,可是这些“向量”所指向的处理程序却一般都是在用户空间中。
8、如何将管道用于进程间通信呢?
1)进程A创建一个管道,创建完成时代表管道两端的两个已打开文件都在进程A中。
2)进程A通过fork()创建出进程B,在fork()的过程中进程A的打开文件表按原样复制到进程B中。
3)进程A关闭管道的读端,而进程B关闭管道的写端。于是,管道的写端在进程A中而读端在进程B中,成为父子进程之间的通信管道。
4)进程A又通过fork()创建进程C,然后关闭其管道写端而与管道脱离关系,使得管道的写端在进程C中而读端在进程B中,成为两个兄弟进程之间的管道。
5)进程C和进程B各自通过exec()执行各自的目标程序,并通过管道进行单向通信。
新年快乐!