进程间通信

一.管道:

1.特点:单向、半双工、缓冲区大小受限制、传输的是无格式的字节流

2.无名管道和有名管道

2.1 无名管道:只能用于有亲缘关系的进程使用(父子进程或兄弟进程)

2.1.1 函数原型:无名管道

#include<unistd.h>

//fd[0]只能用于读,fd[1]只能用于写,一般文件的 1/0 函数都可以用于管道, 如 close、 read、 write. 
int pipe(int fd[2]);

 

2.2 有名管道:它提供一个路径名与之关联,以FIFO的形式存在于文件系统中;可以使互不相关的两个进程间实现彼此通信;该管道可 以通过路径名来指出,并且在文件系统中是可见的。 在建立了管道之后,两个进程就可以把 它当作普通文件一样进行读写操作,使用非常方便;FIFO 严格地遵循先进先出规则,对 管道及 FIFO 的读操作总是从开始处返回数据,对它们的写操作则是把数据添加到末尾

2.2.1 函数原型:有名管道

#include <sys/types.h> 
#include <sys/stat.h>

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

int mkfifo (canst char * pathname, mode_t mode)

二.消息队列

1.特点:消息队列用于运行于同一台机器上的进程间通信,它和管道很相似,是一个在系统内核 中用来保存消息的队列,它在系统内核中是以消息链表的形式出现。 解耦、异步、顶峰消除

2.函数原型

2.1 创建新消息队列或取得已存在消息队列

/*
1.key 可以认为是一个端口号,也可以由函数 ftok 生成。
2.msgflg 如果等于IPC_CREAT,若没有该队列,则创建一个并返回新标识符,若己存在则返回原标识符; 
msgflg 如果等于 IPC_EXCL,若没有该队列,则返回-1 ;若已存在,则返回 O; 
*/

int msgget(key_t key,int msgflg) ; 

2.2 向队列读 /写消息

//msgrcv 从队列中取用消息:
ssize_t msgrcv(int msqid , void *msgp, size_t msgsz, long msgtyp, int msgflg); 

//msgsnd 将数据放到消息队列中:
int msgsnd(int msqid, const void *msgp, size_t msgsz,int msgflg);

 

参数中:

① msqid 是消息队列的标识码;

② msgp 是指向消息缓冲区的指针。 此位置用 来暂时存储发送和接收的消息,是一个用户可定义的通用结构,但一般定义为以下结构:
struct msgstru{

long mtype; //大于0

char mtext[512]; 

}
msgsz 是指消息的大小;

msgtyp 是指从消息队列内读取的消息形态。 如果值为零,则表 示消息队列中的所有消息都会被读取。

msgflg :用来指明核心程序在队列没有数据的情况下所应采取的行动。 如果 msgflg 和常 数 IPC_NOWAIT 合用,则在 msgsnd 执行时若是消息队列己满,则 msgsnd将不会阻塞, 而会立即返回;如果执行的是 msgrcv,则在消息队列呈空时,不做等待马上返回-1 ,并设定错误码为 ENOMSG。当 msgflg 为 0 时, msgsnd及 msgrcv在队列呈满或呈空的情形 时,采取阻塞等待的处理模式。 

2.3 设置消息队列属性

/*
参数中的 msgctl 系统调用对 msgqid 标识的消息队列执行 cmd 操作,
系统定义了 3 种 cmd 操作: IPC_STAT、 IPC_SET、 IPC_RMID。 
IPC_STAT 用来获取消息队列对应的 msqid_ds 数据结构, 并将其保存到 buf指定的地址空间; 
IPC_SET 用来设置消息队列的属性,要设置的属性 存储在 buf 中;
IPC_RMID 用来从内核中删除 msqid 标识的消息队列。
*/

int msgctl(int msgqid, int cmd, struct msqid_ds *buf);
 

3.对比

消息队列跟有名管道有不少的相同之处,消息队列进行通信的进程可以是不相关的进程,同时它们都是通过发送和接收的方式来传递数据的。 在命名管道中, 发送数据用 write 函数,接收数据用 read 函数,则在消息队列中,发送数据用 msgsnd 函数, 接收数据用 msgrcv 函数。 而且它们对每个数据都有一个最大长度的限制。 与命名管道相比,消息队列的优势在于: ①消息队列可以独立于发送和接收进程而存 在 ②可以同时通过发送消息 以避免命名管道的同步和阻塞问题,而不需要由进程自己来提供同步方法; ③接收程序可以 通过消息类型有选择地接收数据,而不是像命名管道中那样,只能默认地接收。 

三.共享内存

1.特点:共享内存就是允许两个不相关的进程访问同一个逻辑内存。 共享内存是在两 个正在运行的进程之间共享和传递数据的一种非常有效的方式。 不同进程之间共享的内存通 常安排在同一段物理内存中。 进程可以将同一段共享内存连接到它们 自己的地址空间中,所 有进程都可以访问共享内存中的地址。 而如果某个进程向共享内存写入数据,所做的改动将立即影响到可以访问同一段共享内 存的任何其他进程。 不过,共享内存并未提供同步机制,也就是说,在第一个进程对共享内存的写操作结束 之前,并无自动机制可以阻止第二个进程对它进行读取。 所以通常需要用其他的机制来同步 对共享内存的访问。 

2.函数原型

2.1 创建共享内存

#include <sys/shm.h> 
/*
第一个参数,程序需要提供一个参数 key (非 0 整数),它有效地为共享内存段命名, shmget 函数运行成功时会返回一个与 key 相关的共享内存标识符(非负整数),用于后续的共 享内存函数;调用失败返回-1。 不相关的进程可以通过该函数的返回值访问同一共享内存,它代表程序可能要使用的某 个资源,程序对所有共享内存的访问都是间接的。 程序先通过调用 shmget 函数并提供一个 键,再由系统生成一个相应的共享内存标识符(shmget 函数的返回值)。
第二个参数, size 以字节为单位指定需要共享的内存容量。 
第三个参数, shmfl.g 是权限标志,它的作用与 open 函数的 mode 参数一样,如果要想在 key 标识的共享内存不存在的条件下创建它的话,可以与 IPC_CREAT 做或操作。 共享内存 的权限标志与文件的读写权限一样,举例来说, 0644 表示允许一个进程创建的共享内存被内 存创建者所拥有的进程向共享内存读取和写人数据,同时其他用户创建的进程只能读取共享 内存
*/

int shmget(key_ t key, int size, int flag) ; 

2.2使用共享内存

/*
shmid 为 shmget 函数返回的共享存储标识符;
addr 和 flag 参数决定了以什么方式来确定连接的地址;
函数的返回值即是该进程数据段所连接的实际地址,其他进程可以对此进程进行读写操作。 
*/
void *shmat(int shmid, void *addr, int flag) ;

2.3分离共享内存

/*
shmdt 函数用于将共享内存从当前进程中分离。 
注意,将共享内存分离并不是删除它,只是使该共享内存对当前进程不再可用。
参数 shmaddr 是 shmat 函数返回的地址指针,调用成功时返回 0,失败时返回-1。 
*/
int shmdt(const void *shmaddr) ; 

3.优缺点

( 1 )优点:使用共享内存进行进程间的通信非常方便,而且函数的接口也简单,数据的 共享还使进程间的数据不用传送,而是直接访问内存,也加快了程序的效率。 同时,它也不 像无名管道那样要求通信的进程有一定的父子关系。

(2 )缺点:共享内存没有提供同步的机制,这使得在使用共享内存进行进程间通信时, 往往要借助其他的手段来进行进程间的同步工作。
 

四.信号量

1.特点:可以解决通信的同步问题

2.函数原型

2.1信号量的创建

#include <sys/types.h> 
#include <sys/ipc.h> 
#include <sys/sem.h>
/*
该函数执行成功返回信号量标示符,失败则返回-1。
参数 key 是函数通过调用ftok得到的键值,nsems 代表创建信号量的个数,如果只是访问而不创建则可以指定该参数为 0 ;但一旦创建了该信号量,就不能更改其信号量个数。 只要不删除该信号量,就可以重新 调用该函数创建该键值的信号量,该函数只是返回以前创建的值,而不会重新创建。 
semfig指定该信号量的读写权限, 当创建信号量时不许加 IPC_CREAT,若指定 IPC_CREAT|IPC_EXCL后创建时发现存在该信号量,创建失败。
*/
int semget(key_ t key, int nsems , int semflg) ; 

2.2信号量的改变

/*
sem_id 是由 semget 返回的信号量标识符, sembuf结构的定义如下:
struct sembuf
{ 
short sem_num; //除非使用一组信号量,否则它为 O 
short sem_op;  //信号量在一次操作中需要改变的数据,通常是两个数,一个是-1,即 p (等待)操作,一个是+1,即 v (发送信号)操作。  
short sem_flg; //通常为 SEM_UNDO,使操作系统跟踪信号,并在进程没有释放该信号量而终止时,操作系统释放信号量
*/

int semop(int semid, struct sembuf *sops , unsigned nsops);

2.3信号量的控制

/*
如果有第 4 个参数,它通常是一个 union semum 结构,定义如下:
union semun{ 
int val; 
struct semid_ds *buf;
unsigned short *arry; 
}

前两个参数与前面一个函数中的一样, cmd 通常是 SETVAL 或 IPC RMID。 SETVAL 用来把信号量初始化为一个己知的值。 p 值通过 union semun 中的 val 成员设置,其作用是 在信号量第一次使用前对它进行设置。 IPC_RMID 用于删除一个已经无须继续使用的信号量 标识符。
*/ 

int semctl (int semid, int semnum, int cmd, ... ) ; 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本火锅店点餐系统采用Java语言和Vue技术,框架采用SSM,搭配Mysql数据库,运行在Idea里,采用小程序模式。本火锅店点餐系统提供管理员、用户两种角色的服务。总的功能包括菜品的查询、菜品的购买、餐桌预定和订单管理。本系统可以帮助管理员更新菜品信息和管理订单信息,帮助用户实现在线的点餐方式,并可以实现餐桌预定。本系统采用成熟技术开发可以完成点餐管理的相关工作。 本系统的功能围绕用户、管理员两种权限设计。根据不同权限的不同需求设计出更符合用户要求的功能。本系统中管理员主要负责审核管理用户,发布分享新的菜品,审核用户的订餐信息和餐桌预定信息等,用户可以对需要的菜品进行购买、预定餐桌等。用户可以管理个人资料、查询菜品、在线点餐和预定餐桌、管理订单等,用户的个人资料是由管理员添加用户资料时产生,用户的订单内容由用户在购买菜品时产生,用户预定信息由用户在预定餐桌操作时产生。 本系统的功能设计为管理员、用户两部分。管理员为菜品管理、菜品分类管理、用户管理、订单管理等,用户的功能为查询菜品,在线点餐、预定餐桌、管理个人信息等。 管理员负责用户信息的删除和管理,用户的姓名和手机号都可以由管理员在此功能里看到。管理员可以对菜品的信息进行管理、审核。本功能可以实现菜品的定时更新和审核管理。本功能包括查询餐桌,也可以发布新的餐桌信息。管理员可以查询已预定的餐桌,并进行审核。管理员可以管理公告和系统的轮播图,可以安排活动。管理员可以对个人的资料进行修改和管理,管理员还可以在本功能里修改密码。管理员可以查询用户的订单,并完成菜品的安排。 当用户登录进系统后可以修改自己的资料,可以使自己信息的保持正确性。还可以修改密码。用户可以浏览所有的菜品,可以查看详细的菜品内容,也可以进行菜品的点餐。在本功能里用户可以进行点餐。用户可以浏览没有预定出去的餐桌,选择合适的餐桌可以进行预定。用户可以管理购物车里的菜品。用户可以管理自己的订单,在订单管理界面里也可以进行查询操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值