学习IPC进程间通信的总结(第八周)



10月24日晚上,回到宿舍准备写这周的总结时,看了下课表突然意识到这已经是第八周,不得不说时间过得真快,与前两年轻松的、无任务的课程相比,今年真是充实了太多!这也许是感觉时间过得快的原因,但是最近我也遇到了许多问题,当接触的知识多了以后,发现自己要学的东西太多了,仅仅上课所学远远不够,所以课后自学了一些课程,遇到的问题一是自己好高骛远,总想急于求成,这看一点那看一点,没有系统的全面的琢磨一本书,问题二:对于应用方面的知识学到手很快,但也会很快的忘记,到了应用时只记得一些概念了。对于这两个问题,我进行了一些思考,施行如下:在学习的时候把重要的知识点记录下来,我自己用的是有道云笔记,新学到的知识或者 不会的问题,通过查阅资料解决的 都把他们记录下来。效果不错,每周都可以回顾查看。最近开设了自己的博客,写博客是为了总结每日所学,反思自身。古人说“吾日三省吾身”还是很有道理的。在自己博客中进行知识总结,以及每周每月思考回顾总结,感觉收获良多。另外,自己也有了一些新的感悟,我们每每感叹许多技术大牛,博客名人如何厉害,其实我们自己就可以成为技术上的leader,其一就是知识及项目经验的不断积累,其二,我认为就是学习知识时对细节的把握,其三,可以持之以恒,不断的学习新技术,平时不断的回顾,“温故而知新”。说了很多,实践为真,接下来还要继续自己的求知之旅。好了下面进行本周的知识总结。



本周进行了两天的授课,和三天的实训;主要讲解了Linux进程与线程编程中的进程之间的通信这一方面知识。总结如下:

下面是我对这几种方法的理解:

1、无名管道(pipe ):管道是一种半双工的通信方式,数据只能单向流动,而且只能在父子进程间通信。管道的缓冲区是有限的(管道存在于内存中,在管道创建时,为缓冲区分配一个页面大小);管道所传送的是无格式字节流,要求管道的读出方和写入方必须事先约定好数据的格式。

进程A   fork()出一个进程B,进程B是复制进程A的副本,得到了进程A的全部资源,因此,进程B也会有指向pd[1]的写指针,指向pd[0]的读指针。

所以管道这样设计:

  进程A:

    Close( fd [0]);

    Write( fd[1],buffer,sizeof(buffer));

  进程B:

    Close(fd [1]);

    Read( fd[0],buf,sizeof(buf));

2、命名管道(fifo):命名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信。严格遵循先进先出(first in first out),对管道及FIFO的读总是从开始处返回数据,对它们的写则把数据添加到末尾。诸如不支持lseek()等文件定位操作。

(1)管道应用的一个重大限制是它没有名字,因此,只能用于具有亲缘关系的进程间通信,在有名管道(named pipe或FIFO)提出后,该限制得到了克服。FIFO不同于管道之处在于它提供一个路径名与之关联,以FIFO的文件形式存在于文件系统中。这样,即使与FIFO的创建进程不存在亲缘关系的进程,只要可以访问该路径,就能够彼此通过FIFO相互通信(能够访问该路径的进程以及FIFO的创建进程之间),因此,通过FIFO不相关的进程也能交换数据。值得注意的是,FIFO严格遵循先进先出(first in first out),对管道及FIFO的读总是从开始处返回数据,对它们的写则把数据添加到末尾。它们不支持诸如lseek()等文件定位操作。

(2)有名管道的创建

int mkfifo(const char * pathname, mode_t mode);

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

(3)有名管道的打开规则

有名管道比管道多了一个打开操作:open。

FIFO的打开规则:

如果当前打开操作是为读而打开FIFO时,若已经有相应进程为写而打开该FIFO,则当前打开操作将成功返回;否则,可能阻塞直到有相应进程为写而打开该FIFO(当前打开操作设置了阻塞标志);或者,成功返回(当前打开操作没有设置阻塞标志)。

如果当前打开操作是为写而打开FIFO时,如果已经有相应进程为读而打开该FIFO,则当前打开操作将成功返回;否则,可能阻塞直到有相应进程为读而打开该FIFO(当前打开操作设置了阻塞标志);或者,返回ENXIO错误(当前打开操作没有设置阻塞标志)。

小结:

管道常用于两个方面:(1)在shell中时常会用到管道(作为输入输入的重定向),在这种应用方式下,管道的创建对于用户来说是透明的;(2)用于具有亲缘关系的进程间通信,用户自己创建管道,并完成读写操作。

FIFO可以说是管道的推广,克服了管道无名字的限制,使得无亲缘关系的进程同样可以采用先进先出的通信机制进行通信。

管道和FIFO的数据是字节流,应用程序之间必须事先确定特定的传输"协议",采用传播具有特定意义的消息。要灵活应用管道及FIFO,理解它们的读写规则是关键。

3、消息队列(message queue ):消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。可以用非先进先出方式处理;消息队列是异步通信的;消息队列有大小限制,通常只用于小数据量的发送;只适用于单台主机的进程间通信;

消息队列:

提供从一个进程向另一个进程发送一个数据块的方法

int msgget(key_t key,int msgflg);

int msgctl(int magid,int cmd,struct msgid_ds *buf);

int msgsnd(int msgid,void *msg_ptr,size_t msg_sz,int msgflag);

int msgrcv(int msgid,void *msg_ptr,size_t msg_sz,long int msg_type,int msgflag);

4、共享内存( shared memory):共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的IPC方式。效率高,进程可以直接读写内存,而不需要任何数据的拷贝;在共享内存段中都是以字符串的默认结束符为一条信息的结尾。每个进程在读写时都遵守这个规则,就不会破坏数据的完整性。

共享内存

允许两个不像关的进程访问同一个逻辑地址

1、int shmget(key_t key,size_t size,int shmflag);

2、void *shmat(int shm_id,const void *shm_addr,int shm_flag);

3、int shmctl(int shm_id,int cmd,struct shmid_ds *buf);

4、int shmdt(const void *shm_addr);

5.信号量(semophore ):信号量是一个计数器,可以用来控制多个进程对共享资源的访问。主要作为进程间以及同一进程内不同线程之间的同步手段。二元信号量:与Mutex类似。

信号量:

int semget(key_t key,int num_sems,int sem_flgs);

int semctl(int sem_id,int sem_num,int command...);

int semop(int sem_id,struct sembuf *sem_ops,size_t num_sem_ops);

每个函数的功能和参数的意义在手册中都能找到。

1、semge创建一个信号量或者获取一个已知信号量的键

key:不相关的进程可以通过他来访问同一个信号量

num_sems:需要的信号量数目。几乎总是1

sem_flags:一组标志,例如IPC_CREAT;

返回值是信号量标志符,给其他信号量函数使用

2、semctl:

sem_id:信号量标志符,semget的返回值

sem_ops:信号量编号,一般取0

command:   就不解释了,在手册中有详细的解释,我就偷偷懒吧。

3、semop

用于改变信号量的值

struct sembuf{

short sen_nums;            //信号量编号,一般取0

short sem_op;               //一般-1是P操作,1是V操作

short sem_flag;            //通常设置为UNDO

}

时间: 2024-10-06 10:14:17

学习IPC进程间通信的总结(第八周)的相关文章

Python学习笔记——进阶篇【第八周】———FTP断点续传作业&批量主机管理工具

主机管理之paramiko模块学习 http://www.cnblogs.com/wupeiqi/articles/5095821.html 作业1:用socketserver继续完善FTP作业 作业2:开发一个批量主机管理工具 需求: 可以对机器进行分组 可以对指定的一组或多组机器执行批量命令,分发文件(发送\接收) 纪录操作日志 作业参考链接http://www.cnblogs.com/alex3714/articles/5227251.html

Python学习笔记——进阶篇【第八周】———异常处理

  引用链接:http://www.cnblogs.com/wupeiqi/articles/5017742.html isinstance(obj,cls) #判断实例是不是在类里 #类似代码 a=[1,2,3] if type(a) is list:print(a) 简便方法: class Foo(object): pass obj = Foo() isinstance(obj,Foo)  issubclass(sub,super) #检查sub是不是super的子类(很少用) class

Python学习笔记——进阶篇【第八周】———Socket编程进阶&多线程、多进程

本节内容: 异常处理 Socket语法及相关 SocketServer实现多并发 进程.线程介绍 threading实例 线程锁.GIL.Event.信号量 生产者消费者模型 红绿灯.吃包子实例 multiprocess实例 进程间通讯 队列Queue 原文目录链接:http://www.cnblogs.com/alex3714/articles/5227251.html 作业1:用socketserver继续完善FTP作业 作业2:开发一个批量主机管理工具 需求: 可以对机器进行分组 可以对指

Python学习笔记——进阶篇【第八周】———CPU运行原理与多线程

CPU运行原理与多线程 什么是线程(thread)? 线程是操作系统能够进行运算调度的最小单位.它被包含在进程之中,是进程中的实际运作单位.一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务 进程是容器,线程是真正执行的任务单元

2017-2018-20155336 《信息安全系统设计基础》第八周学习总结

2017-2018-20155336 <信息安全系统设计基础>第八周学习总结 教材学习内容总结 第11章网络编程 1.客户端-服务器编程模型 一个服务器进程 -> 管理某种资源 -> 通过操作这种资源来为它的客户端提供某种服务 一个或多个客户端进程 基本操作:事务 当一个客户端需要服务时,向服务器发送一个请求,发起一个事务. 服务器收到请求后,解释它,并以适当的方式操作它的资源. 服务器给客户端发送一个相应,并等待下一个请求. 客户端收到响应并处理它. 客户端和服务器都是进程. 2

2018-2019-1 20165228 《信息安全系统设计基础》第八周学习总结

2018-2019-1 20165228 <信息安全系统设计基础>第八周学习总结 教材学习内容总结 并发编程 并发:逻辑控制流在时间上重叠 并发程序:使用应用级并发的应用程序称为并发程序. 三种基本的构造并发程序的方法: 进程,用内核来调用和维护,有独立的虚拟地址空间,显式的进程间通信机制. I/O多路复用,应用程序在一个进程的上下文中显式的调度控制流.逻辑流被模型化为状态机. 线程,运行在一个单一进程上下文中的逻辑流.由内核进行调度,共享同一个虚拟地址空间. 基于进程的并发编程 构造并发程序

2018-2019-1 20165325 《信息安全系统设计基础》第八周学习总结

2018-2019-1 20165325 <信息安全系统设计基础>第八周学习总结 一.学习笔记--网络编程 1.三种并发方式 构造并发程序的方法有三种: 进程 线程 I/O多路复用 进程:用内核来调用和维护,有独立的虚拟地址空间,显式的进程间通信机制. 线程:运行在一个单一进程上下文中的逻辑流.由内核进行调度,共享同一个虚拟地址空间. I/O多路复用:应用程序在一个进程的上下文中显式地调度控制流.逻辑流被模型化为状态机. 2.C/S编程模型 客户端和服务器都是进程,C/S编程模型由一个服务器进

第八周学习进度

本周学习进度   第八周   所花时间(包括上课时间)    10小时      代码量(行)   800       博客量   10       了解到的知识点 了解到了用户的场景分析,以及用户界面设计的作用

20145123刘森明《Java程序设计》第八周学习总结

代码托管地址:http://git.oschina.net/null_289/Java2016 教材学习内容总结 一.日志API 使用日志的起点是Logger类,LOgger实例的创建有许多要处理的要素,LOgger类的构造函数标识为protected,不是java.util.logging同包的类不能直接以new创建,要取得Logger实例,必须使用Logger的静态方法getlogger(). 调用getLogger()是,必须指定Logger实例所属名称空间,名称空间以“.”作为层级区分,