Linux IPC实践(1) -- 概述

进程的同步与互斥

进程同步: 多个进程需要相互配合共同完成一项任务。

进程互斥: 由于各进程要求共享资源,而且有些资源需要互斥使用,因此各进程间竞争使用这些资源,进程的这种关系为进程的互斥;系统中某些资源一次只允许一个进程使用,称这样的资源为临界资源或互斥资源, 而在进程中涉及到互斥资源的程序段叫临界区.

Linux IPC发展

Linux下的进程通信手段基本上是从UNIX平台上的进程通信手段继承而来的。而对UNIX发展做出重大贡献的两大主力AT&T的贝尔实验室及BSD(加州大学伯克利分校的伯克利软件发布中心)在进程间的通信方面的侧重点有所不同。前者是对UNIX早期的进程间通信手段进行了系统的改进和扩充,形成了“system V IPC”,其通信进程主要局限在单个计算机内;而BSD则跳过了该限制,形成了基于套接口(socket)的进程间通信机制。而Linux则把两者的优势都继承了下来.

进程间通信分类

文件

文件锁

管道(pipe)和命名管道(FIFO)

信号(signal)

消息队列

共享内存

信号量

互斥量

条件变量

读写锁

套接字(socket)

进程间共享信息方式

IPC对象的持续性

随进程持续:一直存在直到打开的最后一个进程结束。(如pipe和FIFO(进程结束,数据删除))

随内核持续:一直存在直到内核自举或显式删除(如System V消息队列、共享内存、信号量)

随文件系统持续:一直存在直到显式删除,即使内核自举还存在。(POSIX消息队列、共享内存、信号量如果是使用映射文件来实现)

[IPC对象是由Linux内核管理的]

进程死锁及处理

死锁是指多个进程之间相互等待对方的资源,而在得到对方资源之前又不释放自己的资源,这样,造成循环等待的一种现象。如果所有进程都在等待一个不可能发生的事,则进程就死锁了。

死锁产生的四个必要条件

(1)互斥条件

进程对资源进行排它性使用,即在一段时间内某资源仅为一个进程所占用。

(2)请求和保持条件

当进程因请求资源而阻塞时,对已获得的资源保持不放。

(3)不可剥夺条件

进程已获得的资源在未使用完之前,不能被剥夺,只能在使用完时由自己释放。

(4)环路等待条件

各个进程组成封闭的环形链,每个进程都等待下一个进程所占用的资源

死锁预防

资源一次性分配:(破坏请求和保持条件)

可剥夺资源:破坏不可剥夺条件)

资源有序分配法:(破坏循环等待条件)

死锁避免

预防死锁的几种策略,会严重地损害系统性能。因此在避免死锁时,要施加较弱的限制,从而获得较满意的系统性能。

由于在避免死锁的策略中,允许进程动态地申请资源。因而,系统在进行资源分配之前预先计算资源分配的安全性。若此次分配不会导致系统进入不安全状态,则将资源分配给进程;否则,进程等待。其中最具有代表性的避免死锁算法是银行家算法。

银行家算法

为保证资金的安全,银行家规定:

(1) 当一个顾客对资金的最大需求量不超过银行家现有的资金时就可接纳该顾客;

(2) 顾客可以分期贷款,但贷款的总数不能超过最大需求量

(3) 当银行家现有的资金不能满足顾客尚需的贷款数额时,对顾客的贷款可推迟支付,但总能使顾客在有限的时间里得到贷款

(4) 当顾客得到所需的全部资金后,一定能在有限的时间里归还所有的资金.

哲学家就餐问题

五个哲学家围在一个圆桌就餐,每个人都必须拿起两把叉子才能用餐;

哲学家就餐问题解法:

(1)服务生解法: 将服务生看作是一个管理者, 哲学家在拿叉子之前需要征得服务生的同意;

(2)最多4个哲学家;

(3)仅当一个哲学家两边筷子都可用时才允许他拿筷子;

(4)给所有哲学家编号,奇数号的哲学家必须首先拿左边的筷子,偶数号的哲学家则反之;

信号量

信号量和P、V原语由Dijkstra(迪杰斯特拉)提出, 迪杰斯特拉的三大贡献: goto有害, PV原语, 迪杰斯塔拉最短路算法;

信号量值含义

S>0:S表示可用资源的个数

S=0:表示无可用资源,无等待进程

S<0:|S|表示等待队列中进程个数

PV操作

//信号量定义
typedef struct{
   int value;
   struct process_control_block *list;
}semaphore;
//P原语
//P(semaphore *S)
wait(semaphore *S)
{
    -- S->value;
    if (S->value < 0)
    {
        //将当前进程设置为阻塞状态
        //将当前进程的PCB插入相应的阻塞队列S->list末尾
        block(S->list);
    }
}
//V原语
//V(semaphore *S)
signal(semaphore *S)
{
    ++ S->value;
    if (S->value <= 0)  //表示有进程处于阻塞状态
    {
        //唤醒阻塞队列S->list中等待的一个进程,将其置为就绪态;
        //将其插入就绪队列;
        wakeup (S->list);
    }
}

时间: 2024-10-11 22:02:03

Linux IPC实践(1) -- 概述的相关文章

Linux IPC实践(4) --System V消息队列(1)

消息队列概述 消息队列提供了一个从一个进程向另外一个进程发送一块数据的方法(仅局限于本机); 每个数据块都被认为是有一个类型,接收者进程接收的数据块可以有不同的类型值. 消息队列也有管道一样的不足: (1)每个消息的最长字节数的上限(MSGMAX); (2)系统中消息队列的总条数也有一个上限(MSGMNI); (3)每个消息队列所能够保存的总字节数是有上限的(MSGMNB) . 查看系统限制 cat /proc/sys/kernel/msgmax  #最大消息长度限制 cat /proc/sys

Linux IPC实践(8) --共享内存/内存映射

概述 共享内存区是最快的IPC形式.一旦这样的内存映射到共享它的进程的地址空间,这些进程间数据传递不再涉及到内核,换句话说是进程不再通过执行进入内核的系统调用来传递彼此的数据(如图). 共享内存 VS. 其他IPC形式 用管道/消息队列传递数据 用共享内存传递数据 共享内存生成之后,传递数据并不需要再走Linux内核,共享内存允许两个或多个进程共享一个给定的存储区域,数据并不需要在多个进程之间进行复制,因此,共享内存的传输速度更快! mmap内存映射 将文件/设备空间映射到共享内存区 #incl

Linux IPC实践(7) --Posix消息队列

1. 创建/获取一个消息队列 #include <fcntl.h> /* For O_* constants */ #include <sys/stat.h> /* For mode constants */ #include <mqueue.h> mqd_t mq_open(const char *name, int oflag); //专用于打开一个消息队列 mqd_t mq_open(const char *name, int oflag, mode_t mode

Linux IPC实践(11) --System V信号量(1)

信号量API #include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> int semget(key_t key, int nsems, int semflg); int semctl(int semid, int semnum, int cmd, ...); int semop(int semid, struct sembuf *sops, unsigned nsops); semget int

Linux IPC实践(13) --System V IPC综合实践

实践:实现一个先进先出的共享内存shmfifo 使用消息队列即可实现消息的先进先出(FIFO), 但是使用共享内存实现消息的先进先出则更加快速; 我们首先完成C语言版本的shmfifo(基于过程调用), 然后在此基础上实现C++版本的ShmFifo, 将1块共享内存与3个信号量(1个mutext信号量, 1个full信号量, 1个empty信号量)封装成一个类ShmFifo, 然后编写各自的测试代码; shmfifo说明: 将申请到的共享内存作为一块缓冲区, 将该内存的首部(p_shm到p_pa

Linux IPC实践(9) --System V共享内存

共享内存API #include <sys/ipc.h> #include <sys/shm.h> int shmget(key_t key, size_t size, int shmflg); void *shmat(int shmid, const void *shmaddr, int shmflg); int shmdt(const void *shmaddr); int shmctl(int shmid, int cmd, struct shmid_ds *buf); //

Linux IPC实践(5) --System V消息队列(2)

消息发送/接收API msgsnd函数 int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg); 参数 msgid: 由msgget函数返回的消息队列标识码, 也可以是通过ipcs命令查询出来的一个已经存在的消息队列的ID号 msgp:是一个指针,指针指向准备发送的消息, msgsz:是msgp指向的消息长度, 注意:这个长度不含保存消息类型的那个long int长整型 msgflg:控制着当前消息队列满或到达系统上限时

Linux IPC实践(6) --System V消息队列(3)

消息队列综合案例 消息队列实现回射客户/服务器 server进程接收时, 指定msgtyp为0, 从队首不断接收消息 server进程发送时, 将mtype指定为接收到的client进程的pid client进程发送的时候, mtype指定为自己进程的pid client进程接收时, 需要将msgtyp指定为自己进程的pid, 只接收消息类型为自己pid的消息; // client/server进程接收/发送的数据结构 const int MSGMAX = 8192; struct msgBuf

Linux IPC实践(2) --匿名PIPE

管道概念 管道是Unix中最古老的进程间通信的形式,我们把从一个进程连接到另一个进程的一个数据流称为一个"管道", 管道的本质是固定大小的内核缓冲区; 如:ps aux | grep httpd | awk '{print $2}' 管道限制 1)管道是半双工的,数据只能向一个方向流动:需要双方通信时,需要建立起两个管道; 2)匿名管道只能用于具有共同祖先的进程(如父进程与fork出的子进程)之间进行通信, 原因是pipe创建的是两个文件描述符, 不同进程直接无法直接获得;[通常,一个