一.匿名管道
(1) int pipe(int pipefd[2]);
功能:创建管道 将读端的文件描述符返回到pipefd[0] 将写端文件描述符返回到pipefd[1]
返回值:成功0 失败-1
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
int main()
{
int fd[2];
int ret = pipe(fd);
if(ret<0)
{
perror("pipe");
exit(-1);
}
printf("ceat suc fd[0]:%d fd[1]:%d\n",fd[0],fd[1]);
return 0;
}
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
int main()
{
int fd[2];
int ret = pipe(fd);
if(ret<0)
{
perror("pipe");
exit(-1);
}
size_t ret2 = write(fd[1],"hungry",7);
if(ret2<0)
{
perror("write");
}
char buf[100]="\0";
size_t ret1 = read(fd[0],buf,sizeof(buf));
if(ret1<0)
{
perror("read");
exit(-1);
}
printf("read:%s\n",buf);
return 0;
}
(2)注意:
a、管道中的数据读完就删除 再读 读操作阻塞
b、管道写满 会写阻塞
c、进程结束后 管道文件不存在
d、只能用于亲属关系进程
e、半双工
父子进程间通信:
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/types.h>
int main()
{
int fd[2];
int ret = pipe(fd);
if(ret<0)
{
perror("pipe");
exit(-1);
}
pid_t pid = fork();
if(pid>0)
{
close(fd[1]);
int m;
read(fd[0],&m,sizeof(m));
printf("%d\n",m);
}
else if(pid==0)
{
close(fd[0]);
int n=100;
write(fd[1],&n,sizeof(n));
}
else
{
perror("fork");
}
return 0;
}
练习:父进程从键盘从获取字符串 发送给子进程 子进程获取字符串后 将其转为大写 并输出
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/types.h>
void change(char *p)
{
while(*p)
{
if(*p>='a'&&*p<='z')
{
*p -= 32;
}
p++;
}
}
int main()
{
int fd[2];
int ret = pipe(fd);
if(ret<0)
{
perror("pipe");
exit(-1);
}
pid_t pid = fork();
if(pid>0)
{
char str[1024]="\0";
puts("please input a string:");
scanf("%s",str);
ssize_t ret = write(fd[1],str,sizeof(str));
if(ret<0)
{
perror("write");
exit(-1);
}
}
else if(pid==0)
{
char string[1024]="\0";
ssize_t ret = read(fd[0],string,sizeof(string));
if(ret<0)
{
perror("write");
exit(-1);
}
change(string);
printf("%s\n",string);
}
else
{
perror("fork");
}
return 0;
}
二.有名管道:亲属 非亲属
(1)int mkfifo(const char *pathname, mode_t mode);
功能:按指定的权限创建管道文件
参数1:要创建的管道
参数2:同open 参数3 指定要创建的管道的操作权限
返回值:成功0 失败-1
#include<sys/stat.h>
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
int main()
{
int ret = mkfifo("myfifo",0777);
if(ret<0)
{
perror("mkfifo");
exit(-1);
}
return 0;
}
#include<sys/stat.h>
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<fcntl.h>
int main()
{
int fd = open("myfifo",O_WRONLY);
if(fd<0)
{
perror("open");
exit(-1);
}
puts("open after..............");
char buf[]="good good study";
ssize_t ret = write(fd,buf,sizeof(buf));
if(ret<0)
{
perror("write");
exit(-1);
}
return 0;
}
#include<sys/stat.h>
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<fcntl.h>
int main()
{
int fd = open("myfifo",O_RDONLY);
if(fd<0)
{
perror("open");
exit(-1);
}
char buf[1024]="\0";
ssize_t ret = read(fd,buf,sizeof(buf));
if(ret<0)
{
perror("read");
exit(-1);
}
puts("read after.....");
puts(buf);
return 0;
}
练习:进程a从键盘获取字符串发送给进程b 进程b获取后转为大写 输出
#include<stdlib.h>
#include<unistd.h>
int main()
{
int ret#include<sys/stat.h>
#include<stdio.h>
= mkfifo("myfifo",0777);
if(ret<0)
{
perror("mkfifo");
exit(-1);
}
return 0;
}
#include<sys/stat.h>
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<fcntl.h>
int main()
{
int fd = open("myfifo",O_WRONLY);
if(fd<0)
{
perror("open");
exit(-1);
}
char str[1024];
puts("input a string:");
gets(str);
ssize_t ret = write(fd,str,sizeof(str));
if(ret<0)
{
perror("write");
exit(-1);
}
return 0;
}
#include<sys/stat.h>
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<fcntl.h>
void change(char *p)
{
while(*p)
{
if(*p>='a'&&*p<='z')
{
*p -= 32;
}
p++;
}
}
int main()
{
int fd = open("myfifo",O_RDONLY);
if(fd<0)
{
perror("open");
exit(-1);
}
char buf[1024]="\0";
ssize_t ret = read(fd,buf,sizeof(buf));
if(ret<0)
{
perror("read");
exit(-1);
}
change(buf);
puts(buf);
return 0;
}
练习:进程a从标准输入获取一个人信息(姓名 年龄 体重) 发送给进程b 进程b输出读到的数据
#include"my.h"
int main()
{
int ret = mkfifo("myfifo",0777);
if(ret<0)
{
perror("mkfifo");
exit(-1);
}
return 0;
}
#include"my.h"
int main()
{
int fd = open("myfifo",O_WRONLY);
if(fd<0)
{
perror("open");
exit(-1);
}
person_t x;
puts("input name age weight:");
scanf("%s%d%lf",x.name,&x.age,&x.weight);
ssize_t ret = write(fd,&x,sizeof(x));
if(ret<0)
{
perror("write");
exit(-1);
}
return 0;
}
#include"my.h"
int main()
{
int fd = open("myfifo",O_RDONLY);
if(fd<0)
{
perror("open");
exit(-1);
}
person_t y;
ssize_t ret = read(fd,&y,sizeof(y));
if(ret<0)
{
perror("read");
exit(-1);
}
printf("name:%s age:%d weight:%lf\n",y.name,y.age,y.weight);
return 0;
}
三.信号
1.查看信号列表 kill -l
2.
SIGINT ctrl+c发出的信号
SIGQUIT ctrl+\ 发出的信号 终止程序
SIGILL 非法指令
SIGABRT 通过函数abort()发出的信号 实现程序终止
SIGFPE 浮点异常 除数为0
SIGKILL 必杀信号
SIGPIPE 管道破裂
SIGSEGV 段错误
SIGALRM 通过alarm()发出的信号
SIGTERM 终止信号 kill命令发出的信号
SIGCHLD 子进程停止或终止
SIGCONT 使一个暂停(停止)的进程继续
SIGSTOP 使进程暂停
SIGTSTP ctrl+z发出的信号
3.
信号发送 kill alarm raise
信号接收 while(1) sleep(100000) pause()
信号处理 signal() 默认 忽略 捕捉
(1)signal(信号编号,信号处理方式)
功能:告诉内核 当信号到来时 如何处理信号 —注册信号
信号处理方式3中:
默认 SIG_DFL
忽略 SIG_IGN
捕捉 信号处理函数 处理函数要求:返回值必须为void 形参必须为int
练习1:当用户输入ctrl+\ 会发出SIGQUIT 写程序捕捉这个信号 并打印信号的值
#include"my.h"
void sig_fun(int sig)
{
puts("就不退出.....");
printf("%d\n",sig);//信号编号
}
int main()
{
//signal(SIGINT,SIG_DFL);//默认
//signal(SIGINT,SIG_IGN);//忽略
signal(SIGINT,sig_fun);//告诉内核 当信号SIGINT到来时 调用sig_fun函数
while(1);//保证进程不消亡
return 0;
}
练习2:向数组中赋值 当收到信号SIGINT时
#include"my.h"
#define N 1024
int count;
void sig_fun(int sig)
{
printf("%d\n",count);
}
int main()
{
int arr[N];
int i;
signal(SIGINT,sig_fun);//告诉内核 当信号SIGINT到来时 调用sig_fun函数
for(i=0;i<N;i++)
{
arr[i]=i+1;
count++;
sleep(1);
}
while(1);//保证进程不消亡
return 0;
}
(2)信号接收
#include <unistd.h>
int pause(void);
功能:使当前进程暂停 直到被信号中断
#include"my.h"
void fun(int s)
{
puts("ha~ha~ha~");
}
int main()
{
signal(SIGINT,fun);
puts("before pause ");
pause();
puts("after pause");
}
(3)信号发送
#include <sys/types.h>
#include <signal.h>
1)int kill(pid_t pid, int sig);
功能:向pid进程发送信号sig
返回值:成功0 失败-1
练习:有两个进程 一个进程接收信号SIGINT 收到信号后 将信号编号打印
另一个进程负责发送SIGINT给接收进程
要求:第二个进程 进程PID 及信号 不写固定值 (int main(argc,char*argv[]))
./a.out pid 2
atoi()
//while.c
#include"my.h"
void deal_fun(int sig)
{
printf("%d\n",sig);
}
int main(int argc,char*argv[])
{
if(argc!=2)
{
printf("%s signal\n",argv[0]);
exit(-1);
}
int sig = atoi(argv[1]);
signal(sig,deal_fun);
printf("%d\n",getpid());
pause();
}
//kill.c
#include"my.h"
int main(int argc,char*argv[])
{
if(argc!=3)
{
printf("%s pid sig\n",argv[0]);
exit(-1);
}
int sig = atoi(argv[2]);
int pid = atoi(argv[1]);
int ret = kill(pid,sig);
if(ret<0)
{
perror("kill");
exit(-1);
}
}
2)alarm
unsigned int alarm(unsigned int seconds);
功能:定时 经过指定秒数 系统会自动向本进程发送SIGALRM
#include"my.h"
void sig_fun(int sig)
{
puts("wake up....");
}
int main()
{
signal(SIGALRM,sig_fun);
alarm(3);//3秒后 内核会向本进程发送SIGALRM
while(1);
}
3)raise
int raise(int sig);
功能:发信号给本进程
#include"my.h"
int main()
{
raise(9);//向本进程发送信号SIGKILL
while(1)
{
puts("**************");
sleep(1);
}
}
练习:每隔1s 打印出系统时间 alarm实现
#include"my.h"
void sig_fun(int sig)
{
time_t t=time(NULL);
printf("%s",ctime(&t));
alarm(1);
}
int main()
{
signal(SIGALRM,sig_fun);
alarm(1);
while(1);
}
练习:字母游戏
获取随机字母
键盘输入
匹配
闹铃时间到 统计出1分钟匹配多少个字母
#include"my.h"
int count;
void sig_fun(int sig)
{
printf("%d\n",count*4);
}
int main()
{
char ch,my_ch;
srand(time(NULL));
signal(SIGALRM,sig_fun);
alarm(15);
printf("\nHave Fun Time!\n");
while(1)
{
ch = rand()%26+'a';
printf("%c\n",ch);
my_ch = getchar();
getchar();
if(ch==my_ch)
{
count++;
}
}
return 0;
}
练习:编写程序 创建一个子进程
父进程捕捉信号SIGINT(ctrl+c发 也可以kill命令发)
父进程当捕捉到中断信号后 向子进程发出信号
子进程捕捉到父进程发来的信号 输出:child process is killed by parent!
父进程等待子进程终止后 输出:Parent process exit!
#include"my.h"
pid_t pid;
void sig_fun_father(int s)
{
puts("father catch sigint....");
kill(pid,SIGALRM);
}
void sig_fun_child(int s)
{
puts("child is killed by father!");
exit(0);
}
int main()
{
pid = fork();
if(pid<0)
{
perror("fork");
}
else if(pid>0)//父亲
{
signal(SIGINT,sig_fun_father);
printf("father pid:%d\n",getpid());
wait(NULL);
puts("father exit!");
}
else //子
{
signal(SIGINT,SIG_IGN);
signal(SIGALRM,sig_fun_child);
sleep(1);
printf("child....pid:%d\n",getpid());
while(1);
}
}
#include"my.h"
void fun(int sig)
{
switch(sig)
{
case SIGINT:
puts("不怕CTRL+C");
break;
case SIGQUIT:
puts("就不退出 ");
break;
case SIGTSTP:
puts("我是不会停止滴");
break;
}
}
int main()
{
signal(SIGINT,fun);
signal(SIGQUIT,fun);
signal(SIGTSTP,fun);
while(1);
}
四. 共享内存
共享内存是所有进程间通信方式中效率最高的 最快
步骤:
创建共享内存对象
映射共享内存
对共享内存读写
解除映射
删除共享内存对象
- int shmget(key_t key, size_t size, int shmflg);
功能:创建或打开一个共享内存对象
参数1:标准共享内存 可以是ftok返回值 也可以是IPC_PRIVATE
参数2:新创建的共享内存大小 如果是0 表示取得共享内存对象
参数3:0 表示取得共享内存对象 IPC_CREAT 表示不存在 就创建 IPC_CREAT|0777
返回值:成功返回共享内存标识符 出错-1
ipcs -m 查看共享对象
ipcrm -m shmid 删除共享内存对象
#include<stdlib.h>
#include<stdio.h>
#include<sys/ipc.h>
#include<sys/shm.h>
int main()
{
int shmid = shmget(IPC_PRIVATE,128,IPC_CREAT|0777);
if(shmid<0)
{
perror("shmget");
exit(-1);
}
printf("shmid:%d\n",shmid);
return 0;
}
- key_t ftok(const char *pathname, int proj_id);
功能:成功调用会返回一个key值 失败-1
参数1:文件名包含路径 注意:必须已经存在
参数2:一个整数
返回值:成功返回唯一key值 失败-1
#include<stdlib.h>
#include<stdio.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<sys/types.h>
int main()
{
key_t key = ftok("/home/linux",'a');//
if(key<0)
{
perror("ftok");
exit(-1);
}
int shmid = shmget(key,128,IPC_CREAT|0777);
if(shmid<0)
{
perror("shmget");
exit(-1);
}
printf("shmid:%d\n",shmid);
return 0;
}
- void *shmat(int shmid, const void shmaddr, int shmflg);
功能:将共享内存对象映射到用户空间地址中
参数1:映射的是哪块内存
参数2:映射到用户空间的哪块地址 传NULL 表示系统自动选地址
参数3:0 表示共享内存可读写 SHM_RDONLY 共享内存只读
返回值:成功返回映射后的地址 失败(void)-1 - int shmdt(const void *shmaddr);
功能:解除映射 - shmctl
删除共享内存对象 shmctl(shmid,IPC_RMID,NULL)
//write.c
#include"../my.h"
int main()
{
key_t key = ftok("/home/linux",'a');//
if(key<0)
{
perror("ftok");
exit(-1);
}
int shmid = shmget(key,0,0);
if(shmid<0)
{
perror("shmget");
exit(-1);
}
int *p = shmat(shmid,NULL,0);
if(p==(void*)-1)
{
perror("shmdt");
exit(-1);
}
*p = 100;
shmdt(p);
}
//read.c
#include"../my.h"
int main()
{
key_t key = ftok("/home/linux",'a');//
if(key<0)
{
perror("ftok");
exit(-1);
}
int shmid = shmget(key,0,0);
if(shmid<0)
{
perror("shmget");
exit(-1);
}
int *p = shmat(shmid,NULL,SHM_RDONLY);
if(p==(void*)-1)
{
perror("shmat");
exit(-1);
}
printf("%d\n",*p);
shmdt(p);
shmctl(shmid,IPC_RMID,NULL);
}
练习:进程a发送字符串给进程b 进程b将其转为大写 输出
//creat.c
#include<stdlib.h>
#include<stdio.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<sys/types.h>
int main()
{
key_t key = ftok("/home/linux",'a');//
if(key<0)
{
perror("ftok");
exit(-1);
}
int shmid = shmget(key,128,IPC_CREAT|0777);
if(shmid<0)
{
perror("shmget");
exit(-1);
}
printf("shmid:%d\n",shmid);
return 0;
}
//write.c
#include"../my.h"
int main()
{
key_t key = ftok("/home/linux",'a');//
if(key<0)
{
perror("ftok");
exit(-1);
}
int shmid = shmget(key,0,0);
if(shmid<0)
{
perror("shmget");
exit(-1);
}
char *p = shmat(shmid,NULL,0);
if(p==(void*)-1)
{
perror("shmdt");
exit(-1);
}
puts("input string:");
gets(p);
shmdt(p);
}
//read.c
#include"../my.h"
void changet(char *p)
{
while(*p)
{
if(*p>='a'&&*p<='z')
{
*p -= 32;
}
p++;
}
}
int main()
{
key_t key = ftok("/home/linux",'a');//
if(key<0)
{
perror("ftok");
exit(-1);
}
int shmid = shmget(key,0,0);
if(shmid<0)
{
perror("shmget");
exit(-1);
}
char *p = shmat(shmid,NULL,0);
if(p==(void*)-1)
{
perror("shmat");
exit(-1);
}
changet(p);
printf("%s\n",p);
shmdt(p);
shmctl(shmid,IPC_RMID,NULL);
}
练习2:
一个进程将数据写入共享内存后 用信号通知另一个进程
另一个进程捕捉到信号后 将信息打印出来
//write.c
#include"../my.h"
int main(int argc,char*argv[])
{
if(argc!=2)
{
printf("%s pid\n",argv[0]);
exit(-1);
}
key_t key = ftok("/home/linux",'a');//
if(key<0)
{
perror("ftok");
exit(-1);
}
int shmid = shmget(key,0,0);
if(shmid<0)
{
perror("shmget");
exit(-1);
}
char *p = shmat(shmid,NULL,0);
if(p==(void*)-1)
{
perror("shmdt");
exit(-1);
}
pid_t pid = atoi(argv[1]);
while(1)
{
puts("input string:");
gets(p);
kill(pid,SIGUSR1);
}
}
//read.c
#include"../my.h"
char *p;
void sig_fun(int sig)
{
printf("%s\n",p);
}
int main()
{
signal(SIGUSR1,sig_fun);
printf("%d\n",getpid());
key_t key = ftok("/home/linux",'a');//
if(key<0)
{
perror("ftok");
exit(-1);
}
int shmid = shmget(key,0,0);
if(shmid<0)
{
perror("shmget");
exit(-1);
}
p = shmat(shmid,NULL,0);
if(p==(void*)-1)
{
perror("shmat");
exit(-1);
}
while(1)
{
;
}
}
五.消息队列
- int msgget(key_t key, int msgflg);
功能:创建或打开一个消息队列
参数1:同上
参数2:消息队列的访问权限及打开方式 IPC_CREAT|O_RDONLY
返回值:成功返回消息队列标识符 失败-1
ipcs -q 查看消息队列对象
ipcrm -q msgid 删除消息队列对象
#include"../my.h"
int main()
{
key_t key = ftok("/home",'b');
if(key<0)
{
perror("ftok");
exit(-1);
}
int msgid = msgget(key,IPC_CREAT|0777);
if(msgid<0)
{
perror("msgget");
exit(-1);
}
printf("msgid:%d\n",msgid);
return 0;
}
- int msgsnd(int msqid, const void msgp, size_t msgsz, int msgflg);
功能:将msgp里消息写入msgqid的消息队列
参数2:
struct msgbuf {
long mtype; / message type, must be > 0 /消息类型 必须>0
char mtext[1]; / message data */消息
};
参数3:消息大小 注意!!!:不包括消息类型的大小
参数4: 如果是0 表示消息队列满时 msgsnd会阻塞 如果IPC_NOWAIT 不阻塞
返回值:成功0 失败-1
#include"../my.h"
struct mymsg
{
long type;
int n;
};
int main()
{
key_t key = ftok("/home",'b');
if(key<0)
{
perror("ftok");
exit(-1);
}
struct mymsg m;
m.n = 100;
m.type = 1;
int msgid = msgget(key,O_WRONLY);
if(msgid<0)
{
perror("msgget");
exit(-1);
}
int ret = msgsnd(msgid,&m,sizeof(m)-sizeof(m.type),0);
if(ret<0)
{
perror("msgsnd");
exit(-1);
}
}
- ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
功能:按类型接收消息
参数2:存放消息缓存
参数3:收到的消息的大小 注意:不包括类型大小
参数4:按msgtyp的类型接收消息 如果传0 表示接收任意类型消息
参数5:如果是0 表示没有指定类型的消息 msgrcv会阻塞 如果设置成IPC_NOWAIT 表示不阻塞
//write.c
#include"../my.h"
struct mymsg
{
long type;
int n;
};
int main()
{
key_t key = ftok("/home",'b');
if(key<0)
{
perror("ftok");
exit(-1);
}
struct mymsg m;
puts("input data type");
scanf("%d%ld",&m.n,&m.type);
int msgid = msgget(key,O_WRONLY);
if(msgid<0)
{
perror("msgget");
exit(-1);
}
int ret = msgsnd(msgid,&m,sizeof(m)-sizeof(m.type),0);
if(ret<0)
{
perror("msgsnd");
exit(-1);
}
}
//read.c
#include"../my.h"
struct mymsg
{
long type;
int n;
};
int main()
{
key_t key = ftok("/home",'b');
if(key<0)
{
perror("ftok");
exit(-1);
}
struct mymsg m;
puts("input type:");
scanf("%ld",&m.type);
int msgid = msgget(key,O_RDONLY);
if(msgid<0)
{
perror("msgget");
exit(-1);
}
ssize_t ret = msgrcv(msgid,&m,sizeof(m)-sizeof(m.type),m.type,0);
if(ret<0)
{
perror("msgrcv");
exit(-1);
}
printf("%d\n",m.n);
}
练习:进程a发送字符串给进程b 进程b将其转为大写 输出
//write.c
#include"../my.h"
struct mymsg
{
long type;
char data[1024];
};
int main()
{
key_t key = ftok("/home",'b');
if(key<0)
{
perror("ftok");
exit(-1);
}
struct mymsg m;
puts("input data type");
scanf("%s%ld",m.data,&m.type);
int msgid = msgget(key,O_WRONLY);
if(msgid<0)
{
perror("msgget");
exit(-1);
}
int ret = msgsnd(msgid,&m,sizeof(m)-sizeof(m.type),0);
if(ret<0)
{
perror("msgsnd");
exit(-1);
}
}
//read.c
#include"../my.h"
struct mymsg
{
long type;
char data[1024];
};
void change(char *p)
{
while(*p)
{
if(*p>='a'&&*p<='z')
{
*p -= 32;
}
p++;
}
}
int main()
{
key_t key = ftok("/home",'b');
if(key<0)
{
perror("ftok");
exit(-1);
}
struct mymsg m;
puts("input type:");
scanf("%ld",&m.type);
int msgid = msgget(key,O_RDONLY);
if(msgid<0)
{
perror("msgget");
exit(-1);
}
ssize_t ret = msgrcv(msgid,&m,sizeof(m)-sizeof(m.type),m.type,0);
if(ret<0)
{
perror("msgrcv");
exit(-1);
}
change(m.data);
printf("%s\n",m.data);
}
练习:进程a发送学生信息 姓名 年龄 id 进程b收到后 输出
//write.c
#include"../my.h"
struct mymsg
{
long type;
char name[20];
int age;
int id;
};
int main()
{
key_t key = ftok("/home",'b');
if(key<0)
{
perror("ftok");
exit(-1);
}
struct mymsg m;
puts("input name age id type");
scanf("%s%d%d%ld",m.name,&m.age,&m.id,&m.type);
int msgid = msgget(key,O_WRONLY);
if(msgid<0)
{
perror("msgget");
exit(-1);
}
int ret = msgsnd(msgid,&m,sizeof(m)-sizeof(m.type),0);
if(ret<0)
{
perror("msgsnd");
exit(-1);
}
}
//read.c
#include"../my.h"
struct mymsg
{
long type;
char name[20];
int age;
int id;
};
int main()
{
key_t key = ftok("/home",'b');
if(key<0)
{
perror("ftok");
exit(-1);
}
struct mymsg m;
puts("input type:");
scanf("%ld",&m.type);
int msgid = msgget(key,O_RDONLY);
if(msgid<0)
{
perror("msgget");
exit(-1);
}
ssize_t ret = msgrcv(msgid,&m,sizeof(m)-sizeof(m.type),m.type,0);
if(ret<0)
{
perror("msgrcv");
exit(-1);
}
printf("name:%s age:%d id:%d\n",m.name,m.age,m.id);
}
- msgctl
获取和设置消息队列的属性
格式:msgctl(msgqid,IPC_RMID,NULL)
六.信号量
信号灯:协调进程同步手段 进程异步
- int semget(key_t key, int nsems, int semflg);
功能:创建或取得信号量集对象
参数1:同上
参数2:信号量的个数 一般是1
参数3:可以是0 也可以是IPC_CREAT|0777
返回值:成功返回信号量集对象 失败-1
ipcs -s 查看信号量对象
ipcrm -s semid 删除信号量对象
#include"../my.h"
int main()
{
key_t key = ftok("/home",'a');
int semid = semget(key,1,IPC_CREAT|0777);
if(semid<0)
{
perror("semget");
exit(-1);
}
printf("semdi:%d\n",semid);
return 0;
}
- int semop(int semid, struct sembuf *sops, unsigned nsops);
功能:对信号量集semid进行sops指定的操作
参数2:
struct sembuf{
unsigned short sem_num; /* semaphore number */信号量的编号 一般是0 表示第一个信号量
short sem_op; /* semaphore operation */信号量操作 +1 1 -1
short sem_flg; /* operation flags */如果信号量为负数时 阻塞还是不阻塞 一般是0 表示阻塞
}
参数3:参数2中元素的个数 一般是1
3. semctl
设置信号量的值 semctl(semid,0,SETVAL,3)//设置semid集中 编号为0的信号量值为3
#include"../my.h"
int main()
{
key_t key = ftok("/home",'a');
int semid = semget(key,1,IPC_CREAT|0777);
if(semid<0)
{
perror("semget");
exit(-1);
}
semctl(semid,0,SETVAL,0);
pid_t pid = fork();
if(pid>0)
{
sleep(10);
puts("i am father!");
struct sembuf s;
s.sem_num = 0;
s.sem_op = 1;
s.sem_flg = 0;
semop(semid,&s,1);
puts("father end!");
}
else if(pid==0)
{
struct sembuf s;
s.sem_num = 0;
s.sem_op = -1;
s.sem_flg = 0;
semop(semid,&s,1);
puts("i am child!");
}
semctl(semid,0,IPC_RMID,NULL);//删除信号量集合semid中 编号为0的信号量
return 0;
}