⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 00000006.htm

📁 一份很好的linux入门资料
💻 HTM
📖 第 1 页 / 共 2 页
字号:
<HTML><HEAD>  <TITLE>BBS水木清华站∶精华区</TITLE></HEAD><BODY><CENTER><H1>BBS水木清华站∶精华区</H1></CENTER>发信人:&nbsp;coolzhang&nbsp;(coolzhang),&nbsp;信区:&nbsp;Linux&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<BR>标&nbsp;&nbsp;题:&nbsp;linux&nbsp;bible&nbsp;第五章&nbsp;进程间通讯机制&nbsp;<BR>发信站:&nbsp;BBS&nbsp;水木清华站&nbsp;(Mon&nbsp;Oct&nbsp;25&nbsp;17:48:53&nbsp;1999)&nbsp;<BR>&nbsp;<BR>发信人:&nbsp;coolzhang&nbsp;(coolzhang),&nbsp;信区:&nbsp;UNIX&nbsp;<BR>标&nbsp;&nbsp;题:&nbsp;linux&nbsp;bible&nbsp;第五章&nbsp;进程间通讯机制&nbsp;<BR>发信站:&nbsp;武汉白云黄鹤站&nbsp;(Mon&nbsp;Oct&nbsp;25&nbsp;15:02:50&nbsp;1999),&nbsp;站内信件&nbsp;<BR>&nbsp;<BR>第五章&nbsp;进程间通讯机制&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>进程在核心的协调下进行相互间的通讯。Linux支持大量进程间通讯(IPC)机制。&nbsp;<BR>除了信号和管道外,Linux还支持Unix系统V中的IPC机制。&nbsp;<BR>&nbsp;<BR>5.1&nbsp;&nbsp;信号&nbsp;<BR>&nbsp;<BR>信号是Unix系统中的最古老的进程间通讯方式。它们用来向一个或多个进程发&nbsp;<BR>送异步事件信号。信号可以从键盘中断中产生,另外进程对虚拟内存的非法存&nbsp;<BR>取等系统错误环境下也会有信号产生。信号还被shell程序用来向其子进程发送&nbsp;<BR>任务控制命令。&nbsp;<BR>&nbsp;<BR>系统中有一组被详细定义的信号类型,这些信号可以由核心或者系统中其它具有&nbsp;<BR>适当权限的进程产生。使用kill命令(kill&nbsp;-l)可以列出系统中所有已经定义的&nbsp;<BR>信号。在我的系统(Intel系统)上运行结果如下:&nbsp;<BR>&nbsp;<BR>&nbsp;1)&nbsp;SIGHUP&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2)&nbsp;SIGINT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3)&nbsp;SIGQUIT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4)&nbsp;SIGILL&nbsp;<BR>&nbsp;5)&nbsp;SIGTRAP&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;6)&nbsp;SIGIOT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7)&nbsp;SIGBUS&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;8)&nbsp;SIGFPE&nbsp;<BR>&nbsp;9)&nbsp;SIGKILL&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;10)&nbsp;SIGUSR1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;11)&nbsp;SIGSEGV&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;12)&nbsp;SIGUSR2&nbsp;<BR>13)&nbsp;SIGPIPE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;14)&nbsp;SIGALRM&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;15)&nbsp;SIGTERM&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;17)&nbsp;SIGCHLD&nbsp;<BR>18)&nbsp;SIGCONT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;19)&nbsp;SIGSTOP&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;20)&nbsp;SIGTSTP&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;21)&nbsp;SIGTTIN&nbsp;<BR>22)&nbsp;SIGTTOU&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;23)&nbsp;SIGURG&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;24)&nbsp;SIGXCPU&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;25)&nbsp;SIGXFSZ&nbsp;<BR>26)&nbsp;SIGVTALRM&nbsp;&nbsp;&nbsp;27)&nbsp;SIGPROF&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;28)&nbsp;SIGWINCH&nbsp;&nbsp;&nbsp;&nbsp;29)&nbsp;SIGIO&nbsp;<BR>30)&nbsp;SIGPWR&nbsp;<BR>&nbsp;<BR>当我在Alpha&nbsp;AXP中运行此命令时,得到了不同的信号个数。除了两&nbsp;<BR>个信号外,进程可以忽略这些信号中的绝大部分。其一是引起进程终&nbsp;<BR>止执行的SIGSTOP信号,另一个是引起进程退出的SIGKILL信号。至于其&nbsp;<BR>它信号,进程可以选择处理它们的具体方式。进程可以阻塞信号,如若&nbsp;<BR>不阻塞,则可以在自行处理此信号和将其转交核心处理之间作出选择。&nbsp;<BR>如果由核心来处理此信号,它将使用对应此信号的缺省处理方法。&nbsp;<BR>比如当进程接收到SIGFPE(浮点数异常)时,核心的缺省操作是引起core&nbsp;<BR>dump和进程的退出。信号没有固有的相对优先级。如果在同一时刻对于&nbsp;<BR>一个进程产生了两个信号,则它们将可能以任意顺序到达进程并进行处&nbsp;<BR>理。同时Linux并不提供处理多个相同类型信号的方式。即进程无法区分&nbsp;<BR>它是收到了1个还是42个SIGCONT信号。&nbsp;<BR>&nbsp;<BR>Linux通过存储在进程task_struct中的信息来实现信号。信号个数受到处&nbsp;<BR>理器字长的限制。32位字长的处理器最多可以有32个信号而64位处理器如&nbsp;<BR>Alpha&nbsp;AXP可以有最多64个信号。当前未处理的信号保存在signal域中,&nbsp;<BR>并带有保存在blocked中的被阻塞信号的屏蔽码。除了SIGSTOP和SIGKILL&nbsp;<BR>外,所有的信号都能被阻塞。当产生可阻塞信号时,此信号可以保持一直&nbsp;<BR>处于待处理状态直到阻塞释放。Linux保存着每个进程处理每个可能信号的&nbsp;<BR>信息,它们保存在每个进程task_struct中的sigaction数组中。这些信息&nbsp;<BR>包括进程希望处理的信号所对应的过程地址,或者指示是忽略信号还是由&nbsp;<BR>核心来处理它的标记。通过系统调用,进程可以修改缺省的信号处理过程,&nbsp;<BR>这将改变某个信号的sigaction以及阻塞屏蔽码。&nbsp;<BR>&nbsp;<BR>并不是系统中每个进程都可以向所有其它进程发送信号:只有核心和超级&nbsp;<BR>用户具有此权限。普通进程只能向具有相同uid和gid的进程或者在同一进&nbsp;<BR>程组中的进程发送信号。信号是通过设置task_struct结构中signal域里的&nbsp;<BR>某一位来产生的。如果进程没有阻塞信号并且处于可中断的等待状态,则&nbsp;<BR>可以将其状态改成Running,同时如确认进程还处在运行队列中,就可以通&nbsp;<BR>过信号唤醒它。这样系统下次发生调度时,调度管理器将选择它运行。如&nbsp;<BR>果进程需要缺省的信号处理过程,则Linux可以优化对此信号的处理。例如&nbsp;<BR>SIGWINCH(X窗口的焦点改变)信号,其缺省处理过程是什么也不做。&nbsp;<BR>&nbsp;<BR>信号并非一产生就立刻交给进程,而是必须等待到进程再次运行时才交给&nbsp;<BR>进程。每次进程从系统调用中退出前,它都会检查signal和blocked域,看&nbsp;<BR>是否有可以立刻发送的非阻塞信号。这看起来非常不可靠,但是系统中每个&nbsp;<BR>进程都在不停地进行系统调用,如向终端输出字符。当然进程可以选择去等&nbsp;<BR>待信号,此时进程将一直处于可中断状态直到信号出现。对当前不可阻塞信&nbsp;<BR>号的处理代码放置在sigaction结构中。&nbsp;<BR>&nbsp;<BR>如果信号的处理过程被设置成缺省则由核心来应付它。SIGSTOP信号的缺省&nbsp;<BR>处理过程是将当前进程的状态改变成为Stopped并运行调度管理器以选择一&nbsp;<BR>个新进程继续运行。SIGFPE的缺省处理过程则是引起core&nbsp;dump并使进程退&nbsp;<BR>出。当然,进程可以定义其自身的信号处理过程。一旦信号产生,这个过程&nbsp;<BR>就将被调用。它的地址存储在sigaction结构中。核心必须调用进程的信号&nbsp;<BR>处理例程,具体如何去做依赖于处理器类型,但是所有的CPU必须处理这个&nbsp;<BR>问题:如果信号产生时,当前进程正在核心模式下运行并且马上要返回调用&nbsp;<BR>核心或者系统例程的进程,而该进程处在用户模式下。解决这个问题需要操&nbsp;<BR>纵进程的堆栈及寄存器。进程的程序计数器被设置成其信号处理过程的地址,&nbsp;<BR>而参数通过调用框架或者寄存器传递到处理例程中。当进程继续执行时,信&nbsp;<BR>号处理例程好象普通的函数调用一样。&nbsp;<BR>&nbsp;<BR>Linux是POSIX兼容的,所以当某个特定信号处理例程被调用时,进程可以设&nbsp;<BR>定哪个信号可以阻塞。这意味着可以在进程信号处理过程中改变blocked屏蔽&nbsp;<BR>码。当信号处理例程结束时,此blocked屏蔽码必须设置成原有值。&nbsp;<BR>因此,Linux添加了一个过程调用来进行整理工作,通过它来重新设置被发送&nbsp;<BR>信号进程调用栈中的原有blocked屏蔽码。&nbsp;<BR>对于同一时刻几个信号处理过程,Linux通过堆栈方式来优化其使用,每当一&nbsp;<BR>个处理过程退出时,下一个处理过程必须等到整理例程结束后才执行。&nbsp;<BR>&nbsp;<BR>5.2&nbsp;&nbsp;管道&nbsp;<BR>&nbsp;<BR>一般的Linux&nbsp;shell程序都允许重定向。如&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>$&nbsp;ls&nbsp;|&nbsp;pr&nbsp;|&nbsp;lpr&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>在这个管道应用中,ls列当前目录的输出被作为标准输入送到pr程序中,而&nbsp;<BR>pr的输出又被作为标准输入送到lpr程序中。管道是单向的字节流,它将某个&nbsp;<BR>进程的标准输出连接到另外进程的标准输入。但是使用管道的进程都不会意&nbsp;<BR>识到重定向的存在,并且其执行结果也不会有什么不同。shell程序负责在进&nbsp;<BR>程间建立临时的管道。&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>在Linux中,管道是通过指向同一个临时VFS&nbsp;inode的两个file数据结构来实现&nbsp;<BR>的,此VFS&nbsp;inode指向内存中的一个物理页面。图5.1中每个file数据结构指&nbsp;<BR>向不同的文件操作例程向量,一个是实现对管道的写,另一个从管道中读。&nbsp;<BR>&nbsp;<BR>这样就隐藏了读写管道和读写普通的文件时系统调用的差别。当写入进程对&nbsp;<BR>管道写时,字节被拷贝到共享数据页面中,当读取进程从管道中读时,字节&nbsp;<BR>从共享数据页面中拷贝出来。Linux必须同步对管道的访问。它必须保证读者&nbsp;<BR>和写者以确定的步骤执行,为此需要使用锁、等待队列和信号等同步机制。&nbsp;<BR>&nbsp;<BR>当写者想对管道写入时,它使用标准的写库函数。表示打开文件和打开管道的&nbsp;<BR>描叙符用来对进程的file数据结构集合进行索引。Linux系统调用使用由管道&nbsp;<BR>file数据结构指向的write过程。这个write过程用保存在表示管道的VFS&nbsp;inode&nbsp;<BR>中的信息来管理写请求。&nbsp;<BR>&nbsp;<BR>如果没有足够的空间容纳对所有写入管道的数据,只要管道没有被读者加锁。&nbsp;<BR>则Linux为写者加锁,并把从写入进程地址空间中写入的字节拷贝到共享数据&nbsp;<BR>页面中去。如果管道被读者加锁或者没有足够空间存储数据,当前进程将在管&nbsp;<BR>道inode的等待队列中睡眠,同时调度管理器开始执行以选择其它进程来执行。&nbsp;<BR>如果写入进程是可中断的,则当有足够的空间或者管道被解锁时,它将被读者&nbsp;<BR>唤醒。当数据被写入时,管道的VFSinode被解锁,同时任何在此inode的等待队&nbsp;<BR>列上睡眠的读者进程都将被唤醒。&nbsp;<BR>&nbsp;<BR>从管道中读出数据的过程和写入类似。&nbsp;<BR>&nbsp;<BR>进程允许进行非阻塞读(这依赖于它们打开文件或者管道的方式),此时如果&nbsp;<BR>没有数据可读或者管道被加锁,则返回错误信息表明进程可以继续执行。阻塞&nbsp;<BR>方式则使读者进程在管道inode的等待队列上睡眠直到写者进程结束。当两个进&nbsp;<BR>程对管道的使用结束时,管道inode和共享数据页面将同时被遗弃。&nbsp;<BR>&nbsp;<BR>Linux还支持命名管道(named&nbsp;pipe),也就是FIFO管道,因为它总是按照先进&nbsp;<BR>先出的原则工作。第一个被写入的数据将首先从管道中读出来。和其它管道不&nbsp;<BR>一样,FIFO管道不是临时对象,它们是文件系统中的实体并且可以通过mkfifo&nbsp;<BR>命令来创建。进程只要拥有适当的权限就可以自由使用FIFO管道。打开FIFO管&nbsp;<BR>道的方式稍有不同。其它管道需要先创建(它的两个file数据结构,VFS&nbsp;inode&nbsp;<BR>和共享数据页面)而FIFO管道已经存在,只需要由使用者打开与关闭。在写者&nbsp;<BR>进程打开它之前,Linux必须让读者进程先打开此FIFO管道;任何读者进程从中&nbsp;<BR>读取之前必须有写者进程向其写入数据。FIFO管道的使用方法与普通管道基本&nbsp;<BR>相同,同时它们使用相同数据结构和操作。&nbsp;<BR>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -