unix网络编程进程间通讯第一章简介

#unix网络编程进程间通讯第一章简介
####1.1简介

IPC是(internel process communication) 内核之间的进程通讯,不通进程之间的消息传递,因为像共享内存这样的比较新的通信方式需要某种形式的共同参与和运作

在unix高阶编程30年的演变过程中,消息传递经过了下面的几个阶段

1)管道,这是第一个广泛使用的ipc形式,既可以在程序中使用,也可以在shell中使用。管道的问题在于他们只能具有共同的祖先(父子进程)的进程间使用,不过这个问题已经随着有名管道即FIFO的引入而得到了解决

system v 消息队列,是20世纪80年代加入到内核当中的。他们可以用在同意主机上有学院关系或者没有血缘关系的进程之间.绝大多数的操作系统都是支持他们的

posox消息队列是由posix实时标准加入的,他们可以在同一台主机上有血缘关系的程序和没有血缘关系之间的程序运行

远程过程调用(RPC) 出现在20世纪中期,他是从一个系统上某个程序调用另一个系统上的某个函数的一种方法.既然客户和服务之间通常传递一些信息,而且RPC 可用在同意主机上的客户和服务器之间,因此RPC是另一种消息的传递

需要某种同步形式,防止多个进程同时写一个文件

记录上锁 

system v 信号量

posix 信号量 和 posix共享内存 

互斥锁  和 条件变量(多线程标准)

读写锁

总结 经历阶段:

管道——》system v 消息队列 --》posix标准(消息队列)--》rpc远程过程机器调用


####1.2进程现场之间的信息共享

按照传统的unix编程模式,我们在一个系统中会运行多个进程,每个进程都有各自的地址空间.unix间的信息共享有很多种方式,对此我们做出了总结

1.两个进程之间通过文件系统来共享信息

2.两个进程通过共享内存

3.两个进程通过system v 消息队列来共享驻留在内核中的某些信息。管道是这种共享的一个例子,system v 消息队列和 消息信号量也是

没有任何东西限制任何ipc技术只用于两个进程。我们    讲述的技术试用于任意数目的进程.

线程

虽然unix 系统中出现这个概念已经非常久了.从ipc角度来看,一个给定进程内所有线程共享同样的全局变量(也就是说共享内存区的概念对这种模式来说是内在的).然而我们必须要关注的是各个线程间全局数据的同步问题.同步尽管不是一种明确的IPC形式,但它伴随着多种心事的ipc试用    ,以控制数据共享访问的问题

####1.3 ipc 对象的程序性

我们可以把任意类型的ipc的持续性定义成这个类型的一个对象一直存在

三种类型的持续性:

    进程(随进程持续的IPC,一直存在打开着ipc对象的最后一个进程关闭的对象为止)--》内核(随内核持续的ipc,一直持续到内核重新自举或者显示删除ipc对象为止)--》文件系统(随文件系统持续的ipc,一直存在到显示删除ipc对象为止)
    
    
1)随进程的持续性,ipc对象一直存在到打开着这个对象的最后一个进程关闭该对象为止.(例如fifo和管道就是这个现象)

2)随内核的持续性的ipc对象一直存在到这个内核重新自举或者显示删除该对象为止.例如systemv 消息队列,信号量和共享内存就是这类对象,posix消息队列,信号量和共享内存是随内核持续的,单页是随文件系统持续的取决与实现.

3)随文件系统持续的ipc对象一直存在到显示删除这个对象为止.即使内核重新自举了,这个对象还是保持其值.posix消息队列和信号量共享内存如果使用的是映射文件实现的,那么他们就是随文件系统持续的.

内核自举的含义:

    自举是指上电自检,即内核检查硬件平台都拥有什么硬件,为硬件加载驱动,最终加载根文 件系统并运行第一个进程。

在定义一个ipc对象的持续性的时候我们必须要小心,因为它并不总是像看起来那个样子。例如管道内的数据是在内核中维护的,但管道具备的是随进程持续性而不是随内核的持续行:最后一个将某个管道打开着用于读的进程关闭这个管道后,内核将丢弃所有数据并且删除这个管道.他们只是具备随进程的持续性,因为最后一个将某个fifo打开这的进程关闭该fifo后,fifo的数据就会被全部丢弃

IPC对象持续性

    IPC类型                                            持续性
    管道                                                随进程
    FIFO                                                随进程
    
    POSIX互斥锁                                                                              随进程
    POSIX条件变量                                                                         随进程
    POSIX读写锁                                                                             随进程
    fcntl记录上锁                                                                            随进程
    (还有描述符的阻塞问题)
    
    POSIX消息队列                                                                         随内核
    POSIX有名信号量                                       随内核
    POSIX基于内存的信号量                            随进程
    POSIX共享内存                                        随内核
    
    System v 消息队列                                    随内核
    System v 信号量                                    随内核
    System v共享内存区                                随内核
    
    TCP套接字                                            随进程
    UDP套接字                                            随进程
    unix域套接字                                        随进程
    
注意这个列表中没有任何类型的ipc具备随文件系统的持续性,但是我们说过三种类型的ipc 可能会具有该持续性,这取决于他们的实现。显然,向一个文件写入数据提供了随文件系统的持续性,单这通常不作为一种ipc形式使用。多数形式的ipc并没有在系统重新自举后继续存在的打算,因为进程不可能跨越重新自举继续存货。对于一种给定形式的ipc,要求它具备随文件系统的持续性可能会使其性能降级,而IPC的一个基本的设计目标是高性能.


####1.4 名字空间

当两个或者多个无亲缘关系的进程使用某种类型的IPC对象来彼此交换信息的时候,这个ipc对象必须有一个某种形式的名字或者标示符,这样其中一个进程或者表示服可以创建这个ipc对象,其余进程则可以指定同一个IPC对象.

管道没有名字(因此不能用于没有血缘关系的进程,),但是fifo有一个在文件中的unix路径名作为其表示服(因此可以用在没有血缘关系的进程之间).在以后各章节具体讲述其他ipc的形式时候,我们将使用另外的命名约定.对于一种给定的ipc类型,其可能的名字的集合称为他的名字空间.名字空间十分重要,因为对于普通管道以外的所有形式的ipc来说,名字是客户与服务端彼此连接的十分重要的消息交换手段.

    IPC类型        用于打开或创建ipc的名字空间            ipc打开后的标识
    
    管道            没有名字                            描述符
    FIFO            路径名                                描述符
    
    posix互斥锁         没有名字                            pthread_mutex_t指针
    posix读写锁    没有名字                            pthread_rwlock_t
    posix条件变量   没有名字                            pthread_cond_t
    fcntl记录上锁     文件名字                            描述符
    
    POSIX消息队列    posix IPC名字                        mqd_t值
    POSIX有名信号量 posix ipc名字                        sem_t指针
    基于POSIX内存的信号量   没有名字                    sem_t指针
    POSIX共享内存区    POSIX IPC 名字                 描述符
    
    System v消息队列     key_t建                        System V IPC标识符
    System v信号量    key_t建                        System V IPC标识符
    System v共享内存区  key_t建                        System V IPC标识符
    
    门                    路径名字                         描述符
    Sun RPC              程序/版本                        RPC句柄
    
    TCP套接字            ip地址与tcp端口                描述符
    UDP套接字            ip地址与udp端口                描述符
    Unix域套接字        路径名                            描述符
    
POSIX.1标准化了信号量,他们仍然是可选的特性.对于可选的特性我们在头文件<unistd.h>头文件中定义的常值的名字,例如_POSIX_THREADS.

####1.5 fork exec 和 exit对IPC的影响.

我们需要理解fork、exec和_exit函数对于各种形式的IPC的影响(_exit是由exit调用的一个函数)。

    管道和FIFO:
    fork:子进程取得父进程的所有打开着的描述符副本
    exec:所有打开着的描述符继续打开着,除非已经设置描述符的F_CLOEXEC位
    _exit:关闭所有打开着的描述符,最后一个关闭时候删除管道中或者FIFO中残留的所有数据.

    Posix消息队列
    fork:子进程取得父进程所有打开着的消息队列描述符的副本
    exec:关闭所有打开着的消息队列描述符
    _exit:关闭所有打开着的消息队列描述符

    System V 消息队列:
    fork:没有效果
    exec:没有效果
    _exit:没有效果

    Posix互斥锁和条件变量:
    fork:若驻留在共享内存区中而且具有进程共享属性,则共享
    exec 除非在继续打开着的共享内存区中而且具有进程间共享属性,否则消失
    _exit:除非在继续打开着的共享内存区中而且具有进程间共享属性,否则消失

    POSIX读写锁:
    fork:若驻留在共享内存区中而且具有进程间的共享属性,则进行共享
    exec:除非在继续打开着的共享内存中而且具有进程间的共享属性否则消失
    _exit:除非在继续打开着的共享内存区中而且具有进程间共享属性,否则消失

    POSIX基于内存的信号量:
    fork:若驻留在共享内存区中而且具有进程间共享属性,则共享
    exec:除非在继续打开着的共享内存区中有进程的共享属性,否则消失
    _exit:除非在继续打开着的共享内存区中有进程的共享属性,否则消失

    POSIX有名信号量:
    fork:父进程中所有打开着的有名信号量在子进程中继续打开着
    exec:关闭所有打开着的有名信号量
    exit关闭所有的有名信号量

    system V信号量
    fork:紫禁城中所有semadj值都设置为0
    exec:所有semadj值都协入新的程序中
    exit:所有的semadj值都加到相应的信号量上

    fcntl记录上锁:
    fork:子进程并不继承由父进程持有的锁
    exec:只要描述符继续打开着,锁就不会变
    exit:解开由进程持有的未处理的锁

    mmap内存映射:
    fork:父进程中的内存映射留存到子进程中。
    exec:去除内存映射
    exit:去除内存映射

    posix共享内存区:
    fork:父进程中的内存映射存留到子进程中
    exec:去除内存映射
    exit:去除内存映射

    systemv 共享内存:
    fork:附接着的共享内存区在子进程中继续附接着
    exec:断开所有附接着的共享内存区
    exit:断开所有附接着的共享内存区

    门:
    fork:子进程取得父进程所有打开着的描述符,但是客户在门描述符的激活过程中,只有父进程是服务器
    exec:所有的门描述符都应该关闭,因为他们创建的时候设置了FD_CLOEXEC位
    exit:关闭所有打开着的描述符
    
表中多数特性将在以后的章节中讲述,不过需要强调一些特点。首先,考虑到无名同步变量(互斥所、条件变量、读写锁、基于内存的信号量),从一个具有多个现场中调用fork将变得混乱不堪。在6.1中进行了十分想写的介绍。我们在表中只是简单的注明:如果这些变量在共享内存区中,而且创建时设置了进程间的共享属性,对于能访问该共享内存的任意进程来说,其任意现场能继续访问这些变量。其次,System V IPC 的三种形式没有打开或者关闭的说法。访问这三种形式的ipc需要知道一个标识符,因此知道这个标识符任何进程都可以访问他们,尽管信号量和共享内存可附带提出某种特殊处理要求。

####小结:
ipc传统上是unix一个混杂不堪的领域。虽然有各种各样的解决办法,但是都并不完美,我们主要讨论四个领域

1)消息传递
2)同步
3)内存共享
4)过程调用

我们考虑单个进程之间多个线程间的ipc以及多个进程间的ipc。

各种类型的ipc是可以随进程持续性的、随内核持续性的、或者随文件系统持续性的,取决于ipc对象存在的时间长短。为给定的应用选择ipc类型的时候,我们必须清楚相应ipc的持续性。

各种类型ipc的另一个特性是命名空间,也就是使用ipc对象的进程和线程标识符堆各个ipc对象的方式。各种类型ipc没有名字,有些具有在文件系统中的名字(FIFO)。典型的做法是服务器以某个名字创建一个ipc对象,客户则使用这个名字访问同一个ipc对象

猜你喜欢

转载自blog.csdn.net/qq_32783703/article/details/88530550