Day31、未决信号、有名管道、IPC进程间通讯(消息队列)
来源:互联网 发布:非线性最优化确定参数 编辑:程序博客网 时间:2024/05/01 12:05
补充:
html
apache(web)
C语言写网站后台程序,称作CGI
今天:
一、 未决信号
定义:从信号的产生到信号的到达,在这期间叫做未决信号
sigpending(2)
#include <signal.h>
int sigpending(sigset_t *set);
功能:检查未决信号,将信号集里的未决信号的相应位置1
参数:
set:信号集 (值_结果参数)
返回值:
成功返回0,失败返回1
举例:vi pending.c
1 #include<stdio.h>
2 #include<signal.h>
3 int main(){
4 sigset_t set;
5 sigset_t pset;
6 //清空set
7 sigemptyset(&pset);
8 sigemptyset(&set);
9 //将信号添加到集合set里
10 sigaddset(&set,SIGINT);
11 //设置信号的屏蔽
12 sigprocmask(SIG_SETMASK,&set,NULL);
13 sleep(10);
14 //获取未决信号
15 sigpending(&pset);
16 //判断SIGINT是不是未决信号
17 if(sigismember(&pset,SIGINT)==1){//一次检测一个,这次检测SIGINT,若要检测其他信号,再写if语句
18 printf("SIGINTpending...\n");
19 }
20 return 0;
21 }
tarena@tarena-virtual-machine:~/day31$./a.out
^CSIGINT pending...
作用:在休眠10s内输入ctrl+c,没有反应(阻塞),最后判断SIGINT是不是未决信号
(输入ctrl+c产生了信号,但是被sigprocmask设置屏蔽,此时的信号就是未决信号)
改变:
1#include<stdio.h>
2#include<signal.h>
3int main(){
4 sigset_t set;
5 sigset_t pset;
6 //清空set
7 sigemptyset(&pset);
8 sigemptyset(&set);
9 //将信号添加到集合set里
10 sigaddset(&set,SIGINT);
11 //设置信号的屏蔽
12// sigprocmask(SIG_SETMASK,&set,NULL);
13 sleep(10);
14 //获取未决信号
15 sigpending(&pset);
16 //判断SIGINT是不是未决信号
17 if(sigismember(&pset,SIGINT)==1){
18 printf("SIGINT pending...\n");
19 }
20 return 0;
21 }
tarena@tarena-virtual-machine:~/day31$./a.out
^C
作用:12 // sigprocmask(SIG_SETMASK,&set,NULL);
没有屏蔽ctrl+c的命令,即在睡眠期间,可以接受信号,按下ctrl+c就可以执行打断功能,就不存在未决信号。
二、 有名管道
创建一个管道文件,一个进程往这个文件里写数据,一个进程从这个文件里读取数据,就此完成了两个进程间的通讯。
文件比较特殊,这个文件只是作为进程间通讯使用,文件的大小为0
管道的创建:
mkfifo(3)
#include<sys/types.h>
#include<sys/stat.h>
int mkfifo(const char*pathname, mode_t mode);
功能:创建一个管道文件
参数:
pathname:文件的路径
mode:文件具有的权限,需要考虑umask
返回值:0成功,-1失败,errno被设置
举例:processA.c 先执行,在这个进程中创建管道,往管道里写内容
processB.c 后执行,从管道里读内容
processA.c :
1 #include<stdio.h>
2 #include<unistd.h>
3 #include<sys/types.h>
4 #include<sys/stat.h>
5 #include<fcntl.h>
6 int main(void){
7 int fd,ret;
8 //管道文件的创建
9 ret=mkfifo("myfifo",0666);
10 if(ret==-1){
11 perror("mkfifo");
12 return 1;
13 }
14 //打开管道文件
15 fd=open("myfifo",O_RDWR);
16 if(fd<0){
17 perror("open");
18 return 0;
19 }
20 //往管道文件里写一个字符串
21 write(fd,"tang",5);
22 sleep(10);
23 close(fd);
24 return 0;
25 }
tarena@tarena-virtual-machine:~/day31$ls –l
prw-rw-r--1 tarena tarena 0 9月 8 11:11 myfifo
-rw-rw-r-- 1 tarenatarena 471 9月 8 11:11 processA.c
补充:
1、文件类型:p代表有名管道文件 l 软连接文件 d文件夹问价
2、协议就是规则
processB.c :
1 #include<stdio.h>
2 #include<sys/types.h>
3 #include<sys/stat.h>
4 #include<unistd.h>
5 #include<fcntl.h>
6 int main(void){
7 int fd;
8 char buf[10]={0};
9 //打开管道文件
10 fd=open("myfifo",O_RDONLY);
11 if(fd<0){
12 perror("open");
13 return 1;
14 }
15 //从管道文件里读取字符串
16 read(fd,buf,5);
17 //将读取到的内容输出到屏幕
18 write(1,buf,7);
19 write(1,"\n",1);
20 close(fd);
21 return 0;
22 }
tarena@tarena-virtual-machine:~/day31$gcc processA.c -o pa
tarena@tarena-virtual-machine:~/day31$gcc processB.c -o pb
在一个终端运行:
tarena@tarena-virtual-machine:~/day31$rm myfifo
tarena@tarena-virtual-machine:~/day31$./pa
另一个终端运行:
tarena@tarena-virtual-machine:~/day31$./pb
tang
说明:A进程向B进程传送字符串“tang”
可以使用mkfifo命令创建一个管道文件
mkfifo –m 0666 yfifo
processC.c:从管道文件里写
processD.c:从管道文件里读
processC.c
1 #include<stdio.h>
2 #include<unistd.h>
3 #include<sys/types.h>
4 #include<sys/stat.h>
5 #include<fcntl.h>
6 int main(void){
7 int fd;
8 //打开管道文件
9 fd=open("yfifo",O_RDWR);
10 if(fd<0){
11 perror("open");
12 return 0;
13 }
14 //往管道文件里写一个字符串
15 write(fd,"tang",5);
16 close(fd);
17 return 0;
18 }
processD.c
1 #include<stdio.h>
2 #include<sys/types.h>
3 #include<sys/stat.h>
4 #include<unistd.h>
5 #include<fcntl.h>
6 int main(void){
7 int fd;
8 char buf[10]={0};
9 //打开管道文件
10 fd=open("yfifo",O_RDONLY);
11 if(fd<0){
12 perror("open");
13 return 1;
14 }
15 //从管道文件里读取字符串
16 read(fd,buf,5);
17 //将读取到的内容输出到屏幕
18 write(1,buf,7);
19 write(1,"\n",1);
20 close(fd);
21 return 0;
22 }
tarena@tarena-virtual-machine:~/day31$mkfifo –m 0666 yfifo
tarena@tarena-virtual-machine:~/day31$gcc processC.c -o pc
tarena@tarena-virtual-machine:~/day31$gcc processD.c -o pd
在一个终端执行:
tarena@tarena-virtual-machine:~/day31$ ./pd
(等待进程c输入)
在另一个终端执行:
tarena@tarena-virtual-machine:~/day31$./pc
则第一个终端结果为:
tarena@tarena-virtual-machine:~/day31$./pd
tang
无名管道和有名管道的区别:
无名管道应具有亲缘关系的进程
无名管道不需要进程具有任何关系
三、 有名管道
用户时间
内核时间
睡眠时间
实用计时器
虚拟计时器
真是计时器
setitimer(2)
#include<sys/time.h>
int getitimer(intwhich, struct itimerval *curr_value);
int setitimer(intwhich, const struct itimerval *new_value, struct itimerval *old_value);
功能:设置时间的间隔值
参数:
Which参数的取值:
ITIMER_REAL SIGALRM
ITIMER_VIRTUAL SIGVTALRM
ITIMER_PROF SIGPROF
new_value:
struct itimerval {
struct timeval it_interval; /*next value */
struct timeval it_value; /* current value */
};
struct timeval {
long tv_sec; /* seconds */
long tv_usec; /* microseconds */
};
old_value:NULL
返回值:
0 成功, -1 失败
举例:timer.c
1 /*初始间隔5秒,5秒后,每一秒发送一个SIGALRM*/
2#include<stdio.h>
3#include<signal.h>
4#include<sys/time.h>
5 //信号处理函数
6 voidhandle(int signum){
7 if(signum==SIGALRM){
8 printf("haha...\n");
9 }
10 }
11 intmain(){
12 struct itimerval itm;
13 signal(SIGALRM,handle);
14 //设置初始间隔值
15 itm.it_value.tv_sec=5;
16 itm.it_value.tv_usec=0;
17 //设置重复间隔值
18 itm.it_interval.tv_sec=1;
19 itm.it_interval.tv_usec=0;
20 if(setitimer(ITIMER_REAL,&itm,NULL)==-1){
21 perror("setitimer");
22 return 1;
23 }
24 while(1);
25 return 0;
26 }
tarena@tarena-virtual-machine:~/day31$ ./a.out
haha...
haha...
信号小结:
1、 信号是异步的,是进程间通讯的一种方式
2、 信号的产生、信号的递达、信号未决、信号的捕获
3、 信号的处理方式有三种
a) SIG_DFL 默认处理
b) SIG_IGN 信号忽略
c) 用户自定义处理函数
4、 可重入函数:函数中只出现auto局部变量,这样的函数称为可重入函数
5、 信号的阻塞和未决信号 sigset_t
6、 信号的产生(kill、raise)
7、Sleep、usleep、pause、alarm 重点
8、 Setitimer实现定时器
四、 进程间通讯
进程间通讯的几种方式
1、 管道(有名管道、无名管道)
2、 信号
3、 环境变量(父子进程的传递)
4、 IPC进程间通讯
5、 网络
IPC进程间通讯、
1、消息队列
键
ftok (3)
#include <sys/types.h>
#include <sys/ipc.h>
key_t ftok(const char *pathname, int proj_id);
功能:将文件的路径和proj_id转换成一个IPC键值。
参数:
pathname:文件的路径
proj_id: 0~~255
返回值:
成功返回键值,失败返回-1,erron被设置
msgget (2)
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>
intmsgget(key_t key, int msgflg);
功能:获取一个消息队列的id
返回值:
参数:
Key:通过ftokl(3)获取键
msgflg:IPC_CREAT|IPC_EXCL 如果消息队列存在,调用失败
如果不存在,创建消息队列。创建消息队列的时候还需要指定消息队列的权限,权限等同于open时候的权限
消息队列的消息模板
<linux/msg.h>
Struct msgbuf{
long msgtype;
char mtext[1];
}
msgrcv:(3)
#include <sys/msg.h>
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
功能:从消息队列中读取消息到msgp指定的地址。读取内容的长度由msgsz指定。读取的消息类型由msgtype参数指定。
参数:
msgflg:0
msqid:消息队列的id
msgtyp:消息队列的类型
msgsz:消息内容的长度
msgp:消息队列变量的地址
返回值:
-1:代表失败
成功返回获取到的消息队列的内容的长度
msgsnd (3)
#include <sys/msg.h>
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
功能:向msqid指向的消息队列发送长度为msgsz的消息
参数:
msqid:消息队列的id
msgp:消息队列的具体内容,里面包含消息队列的类型,还有消息队列的内容
msgsz:消息队列的内容的长度
返回值:-1代表失败,errno被设置 0代表成功
举例: send.c recv.c
vi send.c
消息队列的发送
1 #include<stdio.h>
2 #include<sys/types.h>
3 #include<sys/ipc.h>
4 #include<sys/msg.h>
5 #include<string.h>
6 #define FILENAME "."
7 #define PROJ_ID 32
8 int main(void){
9 key_t key;
10 int qid;
11 //定义消息模版的结构体
12 struct mymsgbuf{
13 long msgtype;
14 char str[256];
15 }msgbuff;
16 //初始化消息变量
17 msgbuff.msgtype=3;
18 strcpy(msgbuff.str,"this is atest");
19 //产生一个键值
20 key=ftok(FILENAME,PROJ_ID);
21 if(key==-1){
22 perror("ftok");
23 return 1;
24 }
25 //获取和键值对应的消息队列的id
26 qid=msgget(key,IPC_CREAT|0660);
27 if(qid==-1){
28 perror("msgget");
29 return 2;
30 }
31 printf("msgget successful! \n");
32 int len=sizeof(structmymsgbuf)-sizeof(long);//内容的长度
33 if(msgsnd(qid,&msgbuff,len,0)==-1){
34 perror("msgsnd");
35 return 3;
36 }
37 return 0;
38 }
vi recv.c
消息队列的接收
1 #include<stdio.h>
2 #include<sys/types.h>
3 #include<sys/ipc.h>
4 #include<sys/msg.h>
5 #define FILENAME "."
6 #define PROJ_ID 32
7 int main(void){
8 struct mymsgbuf{
9 long msgtype;
10 char str[256];
11 }msgbuff;
12 key_t key;
13 int qid;
14 key=ftok(FILENAME,PROJ_ID);
15 qid=msgget(key,IPC_CREAT|0660);
16 if(qid==-1){
17 perror("msgget");
18 return 1;
19 }
20 printf("msggetsuccessful...\n");
21 int len=sizeof(structmymsgbuf)-sizeof(long);
22 if(msgrcv(qid,&msgbuff,len,3,0)==-1){
23 perror("msgrcv");
24 return 2;
25 }
26 printf("message is%s\n",msgbuff.str);
27 return 0;
28 }
tarena@tarena-virtual-machine:~/day31$ gcc send.c -o send
tarena@tarena-virtual-machine:~/day31$ gcc recv.c -o recv
tarena@tarena-virtual-machine:~/day31$ ./send
msgget successful!
tarena@tarena-virtual-machine:~/day31$ ipcs
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
------ Message Queues --------
key msqid owner perms used-bytes messages
0x20014e2b 0 tarena 660 256 1
tarena@tarena-virtual-machine:~/day31$ ./recv
msgget successful...
message is this is a test
tarena@tarena-virtual-machine:~/day31$ ipcs
------ Message Queues --------
key msqid owner perms used-bytes messages
0x20014e2b 0 tarena 660 0 0
补充:查看消息队列命令
ipcs 命令用于查看
明天讲:
2、共享内存 (进程映射到同一块内存)
3、信号量集
- Day31、未决信号、有名管道、IPC进程间通讯(消息队列)
- 进程间通讯(一) 有名管道
- Linux 进程间通讯(IPC)详细总结 2有名管道。
- 进程间通讯-有名管道
- 进程间的通讯方式_管道(有名管道)
- 进程间通讯——管道(有名管道)
- Linux进程间通讯--管道(有名管道
- 进程间通信(IPC)2 ------ 有名管道
- 进程间的通讯之有名管道
- 进程间通讯——有名管道
- 进程间通讯(二)IPC之消息队列
- 进程间通信IPC之--无名管道(pipe)和有名管道(fifo)
- APUE读书笔记---进程间通信(IPC)之管道和有名管道(FIFO)
- 进程IPC---管道和有名管道
- Linux IPC(进程间通信)摘要(信号灯,共享内存,消息队列,管道)(一)
- Linux 进程间通讯(IPC)详细总结 4消息队列。
- Linux--进程间通讯IPC(信号量,消息队列,共享内存)
- Linux 进程间通讯(IPC)详细总结 1管道。
- 蜂鸣器
- 华为OJ放苹果&&整数划分
- 103.Binary Tree Zigzag Level Order Traversal
- C语言:单链表的创建,打印及销毁
- Android 看到什么写什么——关于有时候Android studio编写的时候大R丢失并且import出不来的问题
- Day31、未决信号、有名管道、IPC进程间通讯(消息队列)
- shFlags Introduction
- ibm_system 3650安装
- 数据库创建(CREATE),数据库的修改(Update),数据库的删除(ALERT)
- poj2553 The Bottom of a Graph--Kosaraju算法 & 缩点 & 强连通分量
- Maven之(一)Maven是什么
- 完整版点名器
- 文章标题
- 216_实现width宽度充满占满屏幕的底部菜单dialog