找回密码
 注册
关于网站域名变更的通知
查看: 63|回复: 0
打印 上一主题 下一主题

linux的进程通信方案设计

[复制链接]
  • TA的每日心情
    开心
    2023-5-15 15:14
  • 签到天数: 1 天

    [LV.1]初来乍到

    跳转到指定楼层
    1#
     楼主| 发表于 2024-9-2 17:18 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

    EDA365欢迎您登录!

    您需要 登录 才可以下载或查看,没有帐号?注册

    x
    linux下的进程通信手段基本上是从Unix平台上的进程通信手段继承而来的。而对Unix发展做出重大贡献的两大主力AT&T的贝尔实验室及BSD(加州大学伯克利分校的伯克利软件发布中心)在进程间通信方面的侧重点有所不同。前者对Unix早期的进程间通信手段进行了系统的改进和扩充,形成了“system V IPC”,通信进程局限在单个计算机内;后者则跳过了该限制,形成了基于套接口(socket)的进程间通信机制。Linux则把两者继承了下来,如图示:
    / _$ F7 {8 @, t. x8 A
    ; M" q) M0 \7 ^其中,最初Unix IPC包括:管道、FIFO、信号;System V IPC包括:System V消息队列、System V信号灯、System V共享内存区osix IPC包括:Posix消息队列、Posix信号灯、Posix共享内存区。有两点需要简单说明一下:  |- j7 s3 ?3 Q" e- t

    ! s4 R: E' R; [2 E; N' W8 a7 C1)由于Unix版本的多样性,电子电气工程协会(IEEE)开发了一个独立的Unix标准,这个新的ANSI Unix标准被称为计算肪车目梢浦残圆僮飨低辰缑妫≒SOIX)。现有大部分Unix和流行版本都是遵循POSIX标准的,而Linux从一开始就遵循 POSIX标准;; I9 A8 @1 ^% `! S: h
    - m1 h$ N% I7 i* M: H3 S* {2 F! ?
    . j$ N0 G" F1 g4 k
    2)BSD并不是没有涉足单机内的进程间通信(socket本身就可以用于单机内的进程间通信)。事实上,很多Unix版本的单机IPC留有BSD的痕迹,如4.4BSD支持的匿名内存映射、4.3+BSD对可靠信号语义的实现等等。( Q% p0 {7 G/ O6 H+ z- Y% `+ x4 }
    9 V( G0 R6 K2 N/ V: |9 w
    linux下进程间通信的几种主要手段简介:8 I, E1 y4 c9 v5 k! z1 K9 \5 L
    1.管道
    $ j. z! v0 R/ P: r: [9 \6 X/ J, e0 i: `3 b
    管道是进程间通信中最古老的方式,它包括无名管道和有名管道两种,前者可用于具有亲缘关系进程间的通信,即可用于父进程和子进程间的通信,后者额克服了管道没有名字的限制,因此,除具有前者所具有的功能外,它还允许无亲缘关系进程间的通信,即可用于运行于同一台机器上的任意两个进程间的通信。8 o1 U& k5 n8 D6 j; H

    8 S: ^, ?% d( S1 O无名管道由pipe()函数创建:8 ^' w- n' e3 V0 U
    % R! u% h; o' H
    #include
    % _- ^1 x, X6 W9 ~) `
    . J$ F+ T9 g" ]0 Q! S$ tint pipe(int filedis);
    * y, i2 K5 J& g9 u! X8 o( F! z% ~: \, x4 ?; ~5 I
    参数filedis返回两个文件描述符:filedes[0]为读而打开,filedes为写而打开。filedes的输出是filedes[0]的输入。! {4 p1 M) y) q1 B  G( b' ~

    $ X& Q. |- B0 @% h! e6 N在Linux系统下,有名管道可由两种方式创建:命令行方式mknod系统调用和函数mkfifo。下面的两种途径都在当前目录下生成了一个名为myfifo的有名管道:4 G0 N% ]9 ~: t: ~+ _. f! y7 I; V

    " L  \* @& E( [/ W# i* @0 F方式一:mkfifo("myfifo","rw");
    . R8 q6 W7 x7 e$ b
    : L4 [- w0 b. W1 K- q方式二:mknod myfifo p; @& H; p" d* T4 F) y
    8 L/ L# p% f/ h
    生成了有名管道后,就可以使用一般的文件I/O函数如open、close、read、write等来对它进行操作。. {5 e& n) y0 Q0 {+ }3 `

    . q% ~+ s7 ^( f, f* i% h- }) b2.消息队列# x9 X  i, t1 G6 K, {

    0 T2 I( F) |# Z消息队列是消息的链接表,包括Posix消息队列system V消息队列。消息队列用于运行于同一台机器上的进程间通信,它和管道很相似,有足够权限的进程可以向队列中添加消息,被赋予读权限的进程则可以读走队列中的消息。消息队列克服了信号承载信息量少,管道只能承载无格式字节流以及缓冲区大小受限等缺点。% O' ?9 L" U' y0 v8 f1 L9 @: y
    4 c9 b8 y* L& c" z- B
    我们可以用流管道或者套接口的方式来取代它。
    6 r+ V6 [$ u+ j' I" I* c0 K
    9 u: S6 F+ M6 \3.共享内存
    4 W3 K: ^+ G# V. Y; h8 d. D. q. j- c8 N; m, i
    共享内存是运行在同一台机器上的进程间通信最快的方式,因为数据不需要在不同的进程间复制。通常由一个进程创建一块共享内存区,其余进程对这块内存区进行读写。共享内存往往与其它通信机制,如信号量结合使用,来达到进程间的同步及互斥。. w! I  v  Z* g0 J) q

    6 A' [" `2 N& m2 ~$ |首先要用的函数是shmget,它获得一个共享存储标识符。
    9 g( Y9 Y; C" K" F, k( l' @0 I1 p+ C+ y0 F7 Q) _5 \# ]
    #include4 J/ x3 a1 w9 q

    , Q9 B2 ]- l! C5 C" D#include
    . X# k' Z, _. A5 a, r5 L7 _2 X
    8 K* m# C& ?8 I! U* w/ K4 K4 @, B#include  r' w4 V8 m" t/ b. X9 Q$ x- u

    + a, X7 q4 s0 }5 x: Mint shmget(key_t key, int size, int flag);: T# Z5 v) A' |7 |0 S7 j  c  a2 N. i

    8 Q% t& D! `5 }这个函数有点类似大家熟悉的malloc函数,系统按照请求分配size大小的内存用作共享内存。linux系统内核中每个IPC结构都有的一个非负整数的标识符,这样对一个消息队列发送消息时只要引用标识符就可以了。这个标识符是内核由IPC结构的关键字得到的,这个关键字,就是上面第一个函数的key。数据类型key_t是在头文件sys/types.h中定义的,它是一个长整形的数据。在我们后面的章节中,还会碰到这个关键字。
    $ ^/ t. |+ \/ J' Q0 X9 ]
    3 h7 O; f; @$ g  q6 C# e当共享内存创建后,其余进程可以调用shmat()将其连接到自身的地址空间中。
    - Y4 x& N4 Y2 a' I0 m! D$ f9 z8 e
    void *shmat(int shmid, void *addr, int flag);
    0 K, V5 p  N. b, |9 u
    6 z- V) ~1 ~( c% H( s3 wshmid为shmget函数返回的共享存储标识符,addr和flag参数决定了以什么方式来确定连接的地址,函数的返回值即是该进程数据段所连接的实际地址,进程可以对此进程进行读写操作。% p! _- j8 n  x$ \  Q. X/ J
    2 F+ F- W# m1 R  b0 @$ T$ u6 d/ }
    使用共享存储来实现进程间通信的注意点是对数据存取的同步,必须确保当一个进程去读取数据时,它所想要的数据已经写好了。通常,信号量被要来实现对共享存储数据存取的同步,另外,可以通过使用shmctl函数设置共享存储内存的某些标志位如SHM_LOCK、SHM_UNLOCK等来实现。
    1 @' \$ ]3 t7 f8 A6 q( t3 ]; j/ n% Q: i
    4. 信号量
    5 [* O, ^8 W) H/ G
    : \; M2 [% [* C. G  g* c信号量又称为信号灯,它是用来协调不同进程间的数据对象的,而最主要的应用是前一节的共享内存方式的进程间通信。本质上,信号量是一个计数器,它用来记录对某个资源(如共享内存)的存取状况。一般说来,为了获得共享资源,进程需要执行下列操作:5 [5 B+ y" }1 E7 {' W
    " s  H% T) n8 X
    (1) 测试控制该资源的信号量。/ z, {, j  u( }$ @
    8 k7 I$ D# _9 F. y
    (2) 若此信号量的值为正,则允许进行使用该资源。进程将进号量减1。6 @7 A$ F* N1 J! _6 f7 [

    & H8 v! @, @' K(3) 若此信号量为0,则该资源目前不可用,进程进入睡眠状态,直至信号量值大于0,进程被唤醒,转入步骤(1)。: ]7 Y: Z' v+ n3 I
    3 K7 r0 x, I6 X$ v
    (4) 当进程不再使用一个信号量控制的资源时,信号量值加1。如果此时有进程正在睡眠等待此信号量,则唤醒此进程。
    * d& f/ ~$ |& g* x5 T# [' ]% [+ P0 J* `) f) N, Y3 s
    维护信号量状态的是Linux内核操作系统而不是用户进程。我们可以从头文件/usr/src/linux/include/linux /sem.h中看到内核用来维护信号量状态的各个结构的定义。信号量是一个数据集合,用户可以单独使用这一集合的每个元素。要调用的第一个函数是 semget,用以获得一个信号量ID。
    # A3 W, d9 Y  q& s1 H. s3 i, X: V
    #include
    4 d* v. `6 T/ [7 i! t1 J' g% F+ x" J3 @- ]$ I, {, S) U
    #include
    . d9 d, k9 F$ S+ P$ G) X3 l+ z, Q: Q: P0 K
    #include
    * |5 B* d* C. u; a- y9 f/ L' i  o$ ^% ]9 D6 A0 u
    int semget(key_t key, int nsems, int flag);
    ; A8 u9 e5 ~& a4 G' e2 Z( g; m5 [7 l" t& l
    key是前面讲过的IPC结构的关键字,它将来决定是创建新的信号量集合,还是引用一个现有的信号量集合。nsems是该集合中的信号量数。如果是创建新集合(一般在服务器中),则必须指定nsems;如果是引用一个现有的信号量集合(一般在客户机中)则将nsems指定为0。
      h- G2 C7 i' c* u; M2 R1 ?$ @8 U' O  F  C% u: y! X
    sEMCtl函数用来对信号量进行操作。
    0 A$ R: j1 K( C/ v/ n9 P0 Z+ c0 b2 T
    " i3 {  m+ O% p2 E. xint semctl(int semid, int semnum, int cmd, union semun arg);* u& e; }" X9 b, s+ ]% B
    ' l! J$ s# o  S# ~# U
    不同的操作是通过cmd参数来实现的,在头文件sem.h中定义了7种不同的操作,实际编程时可以参照使用。1 S0 k; \2 N  \7 P0 u8 m4 I1 I
    5 q9 m+ B% p# R
    semop函数自动执行信号量集合上的操作数组。" W6 y# V9 \, e2 S

    4 o- e9 x- y; ~int semop(int semid, struct sembuf semoparray[], size_t nops);
      d& V! L& w, K0 K( p+ j; y* m, r9 X6 O5 [% ]
    semoparray是一个指针,它指向一个信号量操作数组。nops规定该数组中操作的数量。
    " c5 [8 N! r" C3 u% @; L& `
    & j4 e+ Q' D! w0 v; o- v下面,我们看一个具体的例子,它创建一个特定的IPC结构的关键字和一个信号量,建立此信号量的索引,修改索引指向的信号量的值,最后我们清除信号量。
    9 T% I: X5 e6 H& F, b4 {9 L- U$ O$ H2 o4 t& E
    5.套接口
    , c+ m6 X( g! |0 O% Y
    * C7 l8 a3 Q) a: Y- ?  ^/ W3 w4 H套接口(socket)编程是实现Linux系统和其他大多数操作系统中进程间通信的主要方式之一。我们熟知的WWW服务、FTP服务、 TELNET服务等都是基于套接口编程来实现的。除了在异地的计算机进程间以外,套接口同样适用于本地同一台计算机内部的进程间通信。
    * i/ b! g. Z, x8 Q  [1 c7 k! a" r$ o, j- A2 t) j
    您需要登录后才可以回帖 登录 | 注册

    本版积分规则

    关闭

    推荐内容上一条 /1 下一条

    EDA365公众号

    关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

    GMT+8, 2025-9-24 05:20 , Processed in 0.140625 second(s), 26 queries , Gzip On.

    深圳市墨知创新科技有限公司

    地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

    快速回复 返回顶部 返回列表