null第3章内容回顾第3章内容回顾了解进程和线程基本概念
掌握进程编程
掌握线程编程
第4章
进程间通信第4章
进程间通信预习检查预习检查进程间通信的方法有?
信号、文件锁、管道、FIFO、信号量、共享内存、消息队列
哪一种方法最有效,最快?
共享内存
哪些方法是system V IPC?
信号量、共享内存、消息队列
必须要求是亲属进程间才能通信的方法是?
管道
本章目标本章目标了解Unix/Linux进程间通信的方式
掌握和熟练运用常见的IPC方式
信号
管道和FIFO
信号量
消息队列
共享内存
本章结构本章结构信号信号信号(signal)机制是Linux系统中最为古老的进程之间的通信机制
信号事件的发生有两个来源:
硬件来源,比如我们按下了键盘或者其它硬件故障;
软件来源,最常用发送信号的系统函数是kill(), raise(), alarm()和setitimer()等函数,软件来源还包括一些非法运算等操作。进程对信号的处理进程对信号的处理进程可以通过三种方式来响应和处理一个信号:
忽略信号
捕捉信号
执行缺省操作
信号处理函数的安装信号处理函数的安装#include
void( *signal(int sig, void( *func)(int)))(int);
如果func不是函数指针,必须是下列两个宏:
SIG_IGN:忽略信号。
SIG_DEF:采用系统默认的方式处理信号,执行缺省操作。
返回值:返回先前的信号处理函数指针,如果有错误则返回-1。要安装的信号值信号的处理
函数 信号的发送信号的发送除了内核和超级用户,并不是每个进程都可以向其他的进程发送信号。
一般的进程只能向具有相同uid和gid的进程发送信号,或向相同进程组中的其他进程发送信号。
常用的发送信号的函数有kill()、raise ()、alarm()、setitimer()、abort() 等。信号的发送信号的发送kill()函数:给指定的进程发送某一个信号
#include
#include
int kill(pid_t pid, int sig);
返回值:成功为0;失败返回-1。
接收信号的进程id要发送的信号值信号的发送信号的发送raise()函数:给进程本身发送一个信号
#include
int raise(int sig);
相当于kill(getpid(),sig);
返回值:成功为0;失败返回-1。
要发送的信号值信号的发送信号的发送alarm()函数:是一个简单定时器,专为SIGALRM信号
设计
领导形象设计圆作业设计ao工艺污水处理厂设计附属工程施工组织设计清扫机器人结构设计
#include
unsigned int alarm(unsigned int seconds);
在指定的seconds秒之后,给进程本身发生一个SIGALRM信号
定时器的定时时间管道管道管道是针对于本地计算机的两个进程之间的通信而设计的通信方法,管道建立后,实际获得两个文件描述符:一个用于读取而另外一个用于写入。
管道是半双工的,数据只能向一个方向流动,需要双方通信时,需要建立起两个管道。
只能用于父子进程或者兄弟进程之间(具有亲缘关心的进程)。
单独构成一种独立的文件系统:管道对于管道两端的进程而言,就是一个文件,但它不是普通的文件,它不属于某种文件系统,而是单独构成一种文件系统,并且只存在于内存中。
数据的读出和写入:一个进程向管道中写的内容被管道另一端的进程读出。写入的内容每次都添加在管道缓冲区的末尾,并且每次都是从缓冲区的头部读出数据。 管道的创建管道的创建系统调用pipe()用于创建一个管道
int pipe(int filedes[2]);
建立管道:
filedes[0]: 为pipe的读出端
filedes[1]: 为pipe的写入端
两个文件描述符数组。
文件描述符FIFOFIFOFIFO不同于管道之处在于它提供一个路径名与之关联,以FIFO的文件形式存在于文件系统中
在文件系统中是一个有名字的管道
任何进程都可以打开
进程间无需关联
FIFO的创建FIFO的创建#include
#include
int mkfifo(const char *pathname, mode_t mode);文件路径名文件权限信号量信号量System IPC中,对于每一个新建的信号量、消息队列以及共享内存,都有一个在整个系统中唯一的标识符。每个标识符也都有唯一对应的关键字,关键字的数据类型由系统定义为key_t。
[alex@alex-/work/tutorail]$ipcs
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x00000000 229376 user 600 393216 2 dest
0x00000000 262145 user 600 393216 2 dest
0x00000000 163842 user 600 393216 2 dest
------ Semaphore Arrays --------
key semid owner perms nsems
0x6406f9da 3080201 alex 600 1
------ Message Queues --------
key msqid owner perms used-bytes messages
0x80600001 0 alex 600 16361 226 创建/获取信号量创建/获取信号量#include
#include
#include
int semget(key_t key, int nsems, int semflg);
Key:键值
1. 指定键值
2. IPC_PRIVATE
系统指定键值
nsems:信号量的数目
信号量集合的数目
Smeflg:信号量标志
1.IPC_CREATE
如果内核中没有此队列,则创建它。
2.IPC_EXECL
当和IPC_CREAT一起使用时,如果队列已经存在,则返回错误。
3.mode_flags:类似于文件的权限
信号量操作信号量操作当进程需要申请或者释放公共资源的时候,可以调用semop()来对信号量进行操作
#include
#include
#include
int semop(int semid, struct sembuf *sops, unsigned nsops);
sops:指向sembuf结构的数组指针
unsigned short sem_num:组中包含的信号量数量
short sem_op:操作类型的整数
整数:加到信号量的值上
负数:信号量的值减去绝对值,如果小于零,进程阻塞,直到信号量的值至少等于其绝对值
0:导致操作阻塞,直到信号量的值为0才继续。
short sem_flg:一个符号位
IPC_NOWAIT: 非阻塞操作
IPC_UNDO:进程退出的时候自动撤销该次操作
nsops:第二个参数数组的长度信号量控制信号量控制信号量控制
#include
#include
#include
int semctl(int semid, int semnum, int cmd, ...);信号量集合中的信号量操作类型消息队列消息队列消息队列是系统内核地址空间中的一个内部的链
表
关于同志近三年现实表现材料材料类招标技术评分表图表与交易pdf视力表打印pdf用图表说话 pdf
。消息可以按照顺序发送到队列中,也可以以几种不同的方式从队列中读取。每一个消息队列用一个唯一的IPC标识符表示。 Msgbuf数据结构 Msgbuf数据结构 struct msgbuf {
long mtype; /* type of message, must > 0*/
char mtext[1]; /* message text */
};
mtype指消息的类型,它由一个整数来代表,并且它只能是大于0的整数。
mtext是消息数据本身。创建消息队列创建消息队列#include
#include
#include
int msgget(key_t key, int msgflg);
Key:键值
1. 指定键值
2. IPC_PRIVATE
系统指定键值
msgflg :信号量标志
1.IPC_CREATE
如果内核中没有此队列,则创建它。
2.IPC_EXECL
当和IPC_CREAT一起使用时,如果队列已经存在,则返回错误。
3.mode_flags:类似于文件的权限
发送和接收消息 发送和接收消息 msgsnd()系统调用用于向队列发送一条消息:
int msgsnd(int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg);
msgrcv()系统调用用于从消息队列读取一条消息:
ssize_t msgrcv(int msqid, struct msgbuf *msgp, size_t msgsz, long msgtyp, int msgflg);消息队列标识符消息缓冲区指针消息大小 0:阻塞
IPC_NOWAIT:非阻塞消息的类型 消息队列的控制 消息队列的控制 通过msgctl()可以对消息队列进行控制或者一些属性的修改:
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
cmd:消息队列的操作
IPC_STAT:读取消息队列的数据结构msqid_ds,并将其存储在buf指定的地址中。
IPC_SET:设置消息队列的数据结构msqid_ds中的ipc_perm、msg_qbytes、msg_ctime元素的值。这个值取自buf参数。
IPC_RMID:从系统内核中移走消息队列。消息队列标识符消息队列属性结构体共享内存共享内存两个不同进程A、B共享内存的基本原理是,同一块物理内存被映射到进程A、B各自的进程地址空间。进程A可以即时看到进程B对共享内存中数据的更新,反之亦然 创建和获取共享内存创建和获取共享内存系统调用shmget()用于创建共享内存或者获取一个已经存在的共享内存的标识符:
int shmget(key_t key, size_t size, int shmflg);
key:键值
1. 指定键值
2. IPC_PRIVATE
系统指定键值
size:共享内存大小
msgflg :共享内存标志
1.IPC_CREATE
如果内核中没有此队列,则创建它。
2.IPC_EXECL
当和IPC_CREAT一起使用时,如果队列已经存在,则返回错误。
3.mode_flags:类似于文件的权限
创建和获取共享内存创建和获取共享内存系统调用shmat()可以获取一个共享内存的地址,并将其连接到进程中:
void *shmat(int shmid, const void *shmaddr, int shmflg);
shmid:
由shmget返回的共享内存标志
shmaddr:
映射该共享内存块的进程内存地址
如果为NULL,Linux将自动选择合适的地址
shmflg:
SHM_RND
SHM_RDONLY
创建和获取共享内存创建和获取共享内存通过shmctl()可以对消息队列进行控制或者一些属性的修改:
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
cmd:共享内存的操作
IPC_STAT:读取一个共享内存的数据结构shmid_ds,并将其存储在buf指定的地址中。
IPC_SET:设置消息队列的数据结构shmid_ds中各个元素的值。这个值取自buf参数。
IPC_RMID:把共亨内存标记为可删除,当最后一个进程脱连此共享内存的时候,系统将删除该共享内存。
共享内存标识符共享内存属性结构体本章总结本章总结共享内存的模型,它是最有效率的进程间通信方式进程间信号量是进程间同步主要方式,信号量操作为负的时候,进程阻塞。直到信号量为正管道是亲戚进程间通信的常用方式,常用于输入输出重定向
Fifo也成为命名管道,可用于无关联进程之间唯一的异步通信机制实验及实验注意事项实验及实验注意事项任务1:使用signal()捕捉信号
任务2:使用kill()函数发送信号
任务3:使用raise()函数发送一个信号
任务4:使用管道传送数据
任务5:使用FIFO来传送数据
任务6:信号量综合
案例
全员育人导师制案例信息技术应用案例心得信息技术教学案例综合实践活动案例我余额宝案例
任务7:消息队列
任务8:共享内存