Linux系统编程——进程间通信(一)

基本操作命令:

ps -ajx/-aux/-ef 查看进程间状态/的相互关系

top 动态显示系统中的进程

nice 按照指定的优先级运行 /renice 改变正在运行的进程的优先级

kill -9杀死进程

jobs 查看后台进程数

进程的结构、类型、状态、模式

0.Linux中进程包括三段:

(1)数据段。存放的是全局变量,常量以及动态内存的数据空间。

(2)正文段。存放的是程序中的代码。

(3)堆栈段。存放的是函数的返回地址,函数的参数以及局部变量。

进程类型:交互进程,既可以在前台运行,也可以在后台运行。该类进程是由shell控制和运行的。

批处理进程,不属于某个终端,被提交到一个队列中以便顺序执行。

守护进程:系统开始时执行,系统关闭时结束。

1.系统中专用的进程:

(1)ID为0的进程是调度进程,通常称为交换进程,该进程是内核的一部分,它并不执行任何磁盘上的程序,因此也被称为系统进程。

(2)ID为1 的进程是init进程,init进程通常读与系统有关的初始化文件,并将系统引导到一个状态。init进程绝不会终止,init进程是所有孤儿进程的父进程。

(3)ID为2的进程是页守护进程,此进程负责支持虚拟存储系统的分页操作。

  2.子进程是父进程的副本,子进程获得父进程的数据空间,堆和栈的副本。这是子进程拥有的独立的空间。父子进程并不共享这些存储空间,父子进程共享正文段。fork之后到底是先执行父进程还是子进程是不一定的,取决于内核所使用的调度算法,如果要求父子进程之间相互同步,则要求进程间的通信。

vfork也能创建进程,但是不能产生父进程的副本,当子进程需要改变内存中的数据时,才拷贝父进程。

父进程与子进程的区别:

fork的返回值不同;

   进程ID不同;

  父进程设置的文件锁不会被子进程继承;

   子进程未处理的闹钟被清除;

  子进程未处理的信号集设置为空集。

(1)孤儿进程:对于所有父进程终止的所有进程,他们的父进程都变为init进程。init无论何时只要有一个进程终止,init就会调用一个wait函数取得其终止状态。这样就防止了系统中好多个僵尸进程。

(2)僵尸进程:子进程结束,父进程没有收尸。

(3)进程间数据共享。

exec函数族:当进程认为自己不能为系统和用户做出任何贡献的时候,就可以调用exec函数族,让自己执行新的程序。如果某个进程在执行一个程序的时候想执行另一个程序,则首先创建子进程,在子进程中间调用exec函数。在用exec函数是要加上出错判断。

传统的进程间通信

(1)无名管道:无名管道是半双工的,数据只能想一个方向流动,具有固定的读端和写端;无名管道只能用于父子进程或者兄弟进程(具有亲缘关系的进程)之间。

无名管道单独构成一种独立的文件系统;管道是基于文件描述符的通信方式,当一个管道建立时,它会创建两个文件描述符,其中fd[0] 固定于读管道,fd[1] 固定于写管道。管道只存在于内存中。

管道的读写:

管道是一种文件,因此对管道的读写同read()和write()函数。

一个进程向管道中写得内容被管道的另一端进程读出。写入的内容每次都添加在管道的尾端,并且每次都是从缓冲区的头部读出数据。

当父子进程对管道进程读写的时候,如果父进程执行写操作,则关闭相应的读管道的文件描述符;而子进程进行写操作,它将关闭相应的读操作。

当管道为空的时候,读操作会阻塞,向管道中写数据的时候Linux操作系统不保证写入的原子操作,管道中只要有空闲区域写进程会试图向管道中写入数据。如果读操作不读走缓冲区的数据,则写操作一直会阻塞。只有在读管道存在时,写管道才有意义,不

然则会受到系统发出的SIGPIPE信号(管道破裂)。应用程序可以处理该信号,也可以忽略(默认动作则是终止程序)。

#include <unistd.h>

int pipe(int fd[2])

(2)有名管道:不同于有名管道之处在于它提供一个路径名与之关联,有名管道可以使不相关的进程之间进行通信。以FIFO的文件形式存在于文件系统中。

注意:FIFO严格遵循先进先出,对管道及FIFO的读总是从开始处返回数据,对他们的写则是把数据添加到末尾。不支持lseek()等文件操作。

#include <sys/types.h>

#include <sys/stat.h>

int mkfifo(const char * pathname, mode_t mode)

该函数的第一个参数是一个普通的路径名,也就是创建后FIFO的名字。第二个参数与打开普通文件的open()函数中的mode 参数相同。如果mkfifo的第一个参数是一个已经存在的路径名时,会返回EEXIST错误,所以一般典型的调用代码首先会检查是否返回该错误,如果确实返回该错误,那么只要调用打开FIFO的函数就可以了。一般文件的I/O函数都可以用于FIFO,如close、read、write等等

无名管道由一个在基本文件系统存储设备上的INODE,一个与其相连的内存INODE,两个打开文件控制块(分别对应管道的信息发送端和信息接收端)及其所属进程的描述信息来标识,在系统执行PIPE(P)命令行之后生成。并在P[0]中返回管道的读通道打开文件描述等,在P[1]中返回管道的写通道打开文件描述符。从结构上看,无名管道没有文件路径名,不占用文件目录项,因此文件目录结构中的链表不适用于这种文件,它只是存在于打开文件结构中的一个临时文件,随其所依附的进程的生存而生存,当进程终止时,无名管道也随之消亡。

送入管道的信息一旦被读进程取用就从管道中消失了,读写操作之间符合先进先出的队列原则。

管道文件是进程间通信的工具,为了尽量少的占用系统存储资源,一般系统均将其限制为最大长度为4096(PIPSIZ)字节的小型文件。当欲写入的消息超过4096字节时,就产生了读、写进程之间的同步问题。首先写操作查找PIPE文件中当前指针的偏移量F-OFFSET,然后从此位置开始尽量写入信息,当长度达到4096字节时,系统控制写进程进入睡眠状态,一直等待读进程取走全部信息时,文件长度指针置0,写进程才被唤醒继续工作。

为防止多个进程同时读写一个管道文件而产生混乱,在管道文件的INODE标志字I-FLAY项中设置了ILOCK标志项,以设置软件锁的方式实现多进程间对管道文件的互斥使用。

无名管道存在着如下两个严重的缺点。

第一,无名管道只能用于连接具有共同祖先的进程。

第二,无名管道是依附进程而临时存在的。所以后来推出了一种无名管道的变种-有名管道,它常被称为FIFO。有名管道除继承了无名管道的所有特性优点之外,还屏弃了无名管道的两个缺点。

首先,FIFO是一种永久性的机构,它具有普通的UNIX系统文件名。在系统下可利用MKNOD命令建立永久的管道,除非刻意删除它,否则它将一直保持在系统中。

其次,正是由于有名管道以“文件名”来标识,所以只要事先约定某一特定文件名,那样所有知道该约定的服务进程,不论它们之间是否有亲属关系,都可以便利地利用管道进行通信。

通过下面的命令可以创建一个命名管道:

/etc/mknod pipe_name p

其中“pipe_name”是要创建的命名管道的名字,参数p 必须出现在命名管道名字之后。

named pipes(命名管道)管道具有很好的使用灵活性,表现在:

1) 既可用于本地,又可用于网络。

2) 可以通过它的名称而被引用。

3) 支持多客户机连接。

4) 支持双向通信。

5) 支持异步重叠I/O操作。

无名管道与有名管道的异同:

1.通信方式;

2.进程是否相关;

3.存在区域不同;

4.存在周期不同;

相同点:

1.都是先进先出;

2.管道的容量相同;

时间: 2024-08-10 15:12:01

Linux系统编程——进程间通信(一)的相关文章

Linux系统编程——进程间通信:信号中断处理

什么是信号? 信号是 Linux 进程间通信的最古老的方式.信号是url=474nN303T2Oe2ehYZjkrggeXCaJPDSrmM5Unoh4TTuty4wSgS0nl4-vl43AGMFbo0_5uH5OQFr_vaRJaZ-3lq_" style="color:rgb(202,0,0); text-decoration:none">软件中断,它是在软件层次上对中断机制的一种模拟,是一种异步通信的方式 . 信号能够导致一个正在执行的进程被还有一个正在执行的异

Linux系统编程——进程间通信:消息队列

消息队列提供了一种在两个不相关的进程之间传递数据的简单高效的方法,其特点如下: 1)消息队列可以实现消息的随机查询.消息不一定要以先进先出的次序读取,编程时可以按消息的类型读取. 2)消息队列允许一个或多个进程向它写入或者读取消息. 3)与无名管道.命名管道一样,从消息队列中读出消息,消息队列中对应的数据都会被删除. 4)每个消息队列都有消息队列标识符,消息队列的标识符在整个系统中是唯一的. 5)消息队列是消息的链表,存放在内存中,由内核维护.只有内核重启或人工删除消息队列时,该消息队列才会被删

Linux系统编程——进程间通信:管道(pipe)

管道的概述 管道也叫无名管道,它是是 UNIX 系统 IPC(进程间通信) 的最古老形式,所有的 UNIX 系统都支持这种通信机制. 无名管道有如下特点: 1.半双工,数据在同一时刻只能在一个方向上流动. 2.数据只能从管道的一端写入,从另一端读出. 3.写入管道中的数据遵循先入先出的规则. 4.管道所传送的数据是无格式的,这要求管道的读出方与写入方必须事先约定好数据的格式,如多少字节算一个消息等. 5.管道不是普通的文件,不属于某个文件系统,其只存在于内存中. 6.管道在内存中对应一个缓冲区.

Linux系统编程——进程间通信:共享内存

概述 共享内存是进程间通信中最简单的方式之一.共享内存允许两个或更多进程访问同一块内存,就如同 malloc() 函数向不同进程返回了指向同一个物理内存区域的指针.当一个进程改变了这块地址中的内容的时候,其它进程都会察觉到这个更改. 共享内存的特点: 1)共享内存是进程间共享数据的一种最快的方法. 一个进程向共享的内存区域写入了数据,共享这个内存区域的所有进程就可以立刻看到其中的内容. 2)使用共享内存要注意的是多个进程之间对一个给定存储区访问的互斥. 若一个进程正在向共享内存区写数据,则在它做

Linux系统编程——进程间通信(System V IPC 对象)

基本查看命令 ipcs  -m查看共享内存        ipcs -s查看信号量        ipcs -q查看消息队列 ipcrm  -m  id 删除共享内存   -M+key值 ipcrm  -s  id 删除信号量 ipcrm  -q  id 删除消息队列 (1)共享内存.为了在多个进程间进行信息交换,内核专门留出了一块内存区,可以由需要访问的进程将其映射到自己的私有地址空间.共享内存允许两个或者更多进程共享一给定的存储区,是一种效率最高的进程间通信方式,因为数据不需要再服务端和客户

Linux系统编程——进程间通信:命名管道(FIFO)

命名管道的概述 无名管道,由于没有名字,只能用于亲缘关系的进程间通信(更多详情,请看<无名管道>).为了克服这个缺点,提出了命名管道(FIFO),也叫有名管道.FIFO 文件. 命名管道(FIFO)不同于无名管道之处在于它提供了一个路径名与之关联,以 FIFO 的文件形式存在于文件系统中,这样,即使与 FIFO 的创建进程不存在亲缘关系的进程,只要可以访问该路径,就能够彼此通过 FIFO 相互通信,因此,通过 FIFO 不相关的进程也能交换数据. 命名管道(FIFO)和无名管道(pipe)有一

Linux系统编程之进程间通信

今天我们接着谈Linux系统编程中的进程间的通信,上一节我们讨论了进程的基本操作.这一节我们来讨论一下进程间的通信.        常见的进程间的通信方式有:无名管道.命名管道.信号.共享内存.消息队列.信号量.套接字. 接下来我们先来谈:                一.无名管道:                      1.管道是UNIX系统的IPC的最古老方式,并且多数unix系统都提供此种通信方式..                      2.管道是一种半双工的通信方式,数据只能

Linux系统编程@进程通信(一)

进程间通信概述 需要进程通信的原因: 数据传输 资源共享 通知事件 进程控制 Linux进程间通信(IPC)发展由来 Unix进程间通信 基于System V进程间通信(System V:UNIX系统的一个分支) POSIX进程间通信(POSIX:可移植操作系统接口,为了提高UNIX环境下应用程序的可移植性.很多其他系统也支持POSIX标准(如:DEC OpenVMS和Windows).) 现在Linux使用的进程间通信方式包括: 管道(pipe).有名管道(FIFO) 信号(signal) 消

Linux网络编程--进程间通信(一)

进程间通信简介(摘自<Linux网络编程>p85) AT&T 在 UNIX System V 中引入了几种新的进程通讯方式,即消息队列( MessageQueues),信号量( semaphores)和共享内存( shared memory),统称为 System V IPC.在Linux 系统编程中,它们有着广泛的应用. System V IPC 的一个显著的特点,是它的具体实例在内核中是以对象的形式出现的,我们称之为 IPC 对象.每个 IPC 对象在系统内核中都有一个唯一的标识符