一、消息队列
特点:
1.相对管道来说接口使用较为复杂
2.生命周期:随内核
3.为数据块服务(管道是字节流)
4.长度会受到一定限制
ipcs - q 查看消息队列资源
ipcrm -q +key/msgid 删除消息队列资源
来看使用例子:
实现功能的文件:
-
#include"common.h"
-
-
static int com_creat_queue(int flags)
-
{
-
key_t key = ftok(_PATH_,_PROJ_ID_);
-
if(key < 0){
-
printf("%d:%s\n",errno,strerror(errno));
-
return -1;
-
}
-
int msg_id = msgget(key,flags);
-
if(msg_id < 0){
-
printf("%d:%s\n",errno,strerror(errno));
-
return -2;
-
}
-
return msg_id;
-
}
-
-
int creat_queue()
-
{
-
int flags = IPC_CREAT|IPC_EXCL|0666;
-
return com_creat_queue(flags);
-
}
-
-
int get_queue()
-
{
-
int flags = IPC_CREAT;
-
return com_creat_queue(flags);
-
}
-
-
int send_msg(int msg_id,int who,char *msg)
-
{
-
struct msgbuf _buf;
-
memset(&_buf,'\0',sizeof(_buf));
-
_buf.mtype = who;
-
strncpy(_buf.mtext,msg,sizeof(msg)+1);
-
printf("say : %s\n",msg);
-
return msgsnd(msg_id,&_buf,sizeof(_buf.mtext),0);
-
}
-
int recv_msg(int msg_id,int want,char out[],int out_len)
-
{
-
struct msgbuf _buf;
-
memset(&_buf,'\0',sizeof(_buf));
-
int ret = msgrcv(msg_id,&_buf,sizeof(_buf.mtext),want,0);
-
if(ret <= -1)
-
{
-
printf("%d:%s\n",errno,strerror(errno));
-
return -1;
-
}
-
memset(out,'\0',out_len);
-
strcpy(out,_buf.mtext);
-
return 0;
-
}
-
int delete_queue(int msg_id)
-
{
-
int ret = msgctl(msg_id,IPC_RMID,NULL);
-
if(ret < 0){
-
printf("%d:%s\n",errno,strerror(errno));
-
return -3;
-
}
-
return 0;
-
}
客户端:
-
#include"common.h"
-
-
int client()
-
{
-
int msg_id = get_queue();
-
char buf[_SIZE_];
-
while(1)
-
{
-
printf("Please Enter : ");
-
fflush(stdout);
-
memset(buf,'\0',sizeof(buf));
-
scanf("%s",buf);
-
send_msg(msg_id,CLIENT_TYPE,buf);
-
if(strncasecmp(buf,"quit",4) == 0){
-
printf("client quit\n");
-
return 0;
-
}
-
sleep(2);
-
memset(buf,'\0',sizeof(buf));
-
int ret = recv_msg(msg_id,SERVER_TYPE,buf,sizeof(buf));
-
if(ret == 0){
-
printf("server say : %s\n",buf);
-
}
-
}
-
}
-
int main()
-
{
-
client();
-
return 0;
-
}
服务端:
-
int server()
-
{
-
int msg_id = creat_queue();
-
if(msg_id < 0){
-
printf("%s\n",strerror(errno));
-
return -1;
-
}
-
char buf[_SIZE_];
-
while(1)
-
{
-
sleep(5);
-
memset(buf,'\0',sizeof(buf));
-
int ret = recv_msg(msg_id,CLIENT_TYPE,buf,sizeof(buf));
-
if(ret == 0){
-
if(strncasecmp(buf,"quit",4) == 0){
-
printf("client leave!\n");
-
break;
-
}
-
printf("client say : %s\n",buf);
-
}
-
printf("Please Enter :");
-
fflush(stdout);
-
memset(buf,'\0',sizeof(buf));
-
scanf("%s",buf);
-
send_msg(msg_id,SERVER_TYPE,buf);
-
}
-
return delete_queue(msg_id);
-
}
-
int main()
-
{
-
server();
-
return 0;
-
}
这样服务端和客户端就可以进行对话了。
二、信号量
特点:
1.本质其实为一个计数器,记录资源的数量
2.PV为原子操作
P(sv):如果sv的值大于零,就给它减1;如果它的值为零,就挂起该进程的执行
V(sv):如果有其他进程因等待sv而被挂起,就让它恢复运行,如果没有进程因等待sv而挂 起,就给它加1.
3.保证临界资源的同步、互斥
ipcs -s 查看信号量
ipcrm -s 删除信号量
使用例子:
-
#include"common.h"
-
-
static int com_sem(int nsems,int flag)
-
{
-
key_t key = ftok(_PATH_,_PROJ_ID_);
-
if(key < 0){
-
printf("%s\n",strerror(errno));
-
return -1;
-
}
-
int sem_id = semget(key,nsems,flag);
-
if(sem_id < 0){
-
printf("%s\n",strerror(errno));
-
return -2;
-
}
-
return sem_id;
-
}
-
-
int creat_sem(int nsems)
-
{
-
int flag = IPC_CREAT|IPC_EXCL|0666;
-
return com_sem(nsems,flag);
-
}
-
-
int get_sem(int nsems)
-
{
-
int flag = IPC_CREAT;
-
return com_sem(nsems,flag);
-
}
-
-
static int com_semop(int sem_id,unsigned short num,short op)
-
{
-
struct sembuf semb[1];//only consider binary semaphore
-
semb[0].sem_num =num;
-
semb[0].sem_op = op;
-
semb[0].sem_flg = 0;//SEM_UNDO,对崩溃的信号量进行回滚操作
-
if(semop(sem_id,semb,1) < 0)
-
{
-
printf("%s\n",strerror(errno));
-
return -1;
-
}
-
return 0;
-
}
-
-
int P(int sem_id,unsigned short num)
-
{
-
int op = -1;
-
return com_semop(sem_id,num,op);
-
}
-
-
int V(int sem_id,unsigned short num)
-
{
-
int op = 1;
-
return com_semop(sem_id,num,op);
-
}
-
-
int init_sem(int sem_id,int num,int init_val)
-
{
-
semun_t sem_val;
-
sem_val.val = init_val;
-
int ret = semctl(sem_id,num,SETVAL,sem_val);
-
if(ret < 0){
-
printf("%s\n",strerror(errno));
-
return -1;
-
}
-
return 0;
-
}
-
int destory_sem(int sem_id)
-
{
-
int ret = semctl(sem_id,0,IPC_RMID);
-
if(ret < 0){
-
printf("%s\n",strerror(errno));
-
return -1;
-
}
-
printf("\ndestroy success!\n");
-
return 0;
-
}
测试:
-
int main()
-
{
-
int f_sem_id = creat_sem(1);
-
init_sem(f_sem_id,0,1);
-
pid_t id = fork();
-
if( id == 0 ){//child
-
int c_sem_id = get_sem(1);
-
int count = 3;
-
while(1){
-
P(c_sem_id,0);
-
printf("A");
-
fflush(stdout);
-
sleep(3);
-
printf("A");
-
fflush(stdout);
-
sleep(3);
-
V(c_sem_id,0);
-
count--;
-
if(count == 0){
-
break;
-
}
-
}
-
}
-
else
-
{//father
-
int count = 3;
-
while(1) {
-
P(f_sem_id,0);
-
printf("B");
-
fflush(stdout);
-
sleep(3;
-
printf("B");
-
fflush(stdout);
-
sleep(2;
-
V(f_sem_id,0);
-
count--;
-
if(count == 0){
-
break;
-
}
-
-
}
-
}
-
}
阅读(1898) | 评论(0) | 转发(0) |