C++学习笔记day31-----UC

进程间的通讯
上一篇笔记描述了system v ipc 有三种进程间通讯的方式。
消息队列
可以通过ftok(2)获得一个进程的键值,可以通过msgget(2)获得一个消息队列的ID。
现在可以通过消息队列的ID来对消息队列进行写入数据和读取数据。
系统提供以下函数来操作这个过程:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
功能:发送消息到消息队列
参数:
msqid:将消息添加到msqid指定的消息队列中
msgp:需要调用者自定义的结构体变量的地址
msgsz:指定了msgp指向的mtext成员的大小
msgflg:
0:阻塞
IPC_NOWAIT:不阻塞
返回值:
error:-1,errno被设置
success:0


msgp指向这样一个结构体类型变量的地址

struct msgbuf {
    long mtype;       /* message type, must be > 0 */
    char mtext[1];    /* message data */
};


ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);
功能:从消息队列移除一条消息,存放到msgp指定的地址空间里
参数:
msqid:指定消息队列,从这个消息队列中移除一条消息
msgp:指定存放消息的结构体的地址空间
msgsz:指定了msgp指向的变量的mtext成员的最大字节数
msgtyp:指定消息的类型,结构体变量的第一个成员变量的值。
msgflg:
参数:
IPC_NOWAIT:非阻塞,请求的消息不存在立即返回错误。不等待
0:阻塞,请求的消息不存在,等待。
返回值:
错误    -1  errno被设置
成功    返回实际拷贝的mtext的成员字节数

通过以下例子来演示上述函数:

/*send*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
typedef struct{
    long mtype;       /* message type, must be > 0 */
    char mtext[128];    /* message data */
}msg_t;
int main(void){
    msg_t msg;
    //获取键值
    key_t key = ftok(".",34);
    if(key == -1){
        perror("ftok");
        return -1;
    }
    //获取队列ID
    int flag_msg = msgget(key,IPC_CREAT|0644);
    if(flag_msg == -1){
        perror("msgget");
        return -1;
    }
    msg.mtype = 3;
    strcpy(msg.mtext,"hello kitty!\n");
    //向队列发送一条消息
    int flag_snd = msgsnd(flag_msg,&msg,strlen(msg.mtext),0);
    if(flag_snd == -1){
        perror("msgsnd");
        return -1;
    }
        return 0;
}
-------------------------------------------------------------------
/*rcv*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
typedef struct{
    long mtype;       /* message type, must be > 0 */
    char mtext[128];    /* message data */
}msg_t;
int main(void){
    msg_t msg;
    //获取键值
    key_t key = ftok(".",34);
    if(key == -1){
        perror("ftok");
        return -1;
    }
    //获取队列ID
    int flag_msg = msgget(key,IPC_CREAT|0644);
    if(flag_msg == -1){
        perror("msgget");
        return -1;
    }
    //从队列移除一条消息
    int flag_rcv = msgrcv(flag_msg,&msg,128,3,0);
    if(flag_rcv == -1){
        perror("msgsnd");
        return -1;
    }
    printf("%s",msg.mtext);
        return 0;
}

在send函数中,向队列发送一条消息,在rcv函数中,接受队列发送的消息。
可以在程序的末尾加入getchar(),让程序暂停,然后通过ipcs来观察队列的连接数,和队列里的消息。
共享内存
共享内存的方式,是将内核中的一块内存映射到进程的虚拟地址空间上,通过操作进程的虚拟地址空间来完成进程间的通讯。
系统提供以下函数用于操作:

#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key, size_t size, int shmflg);
功能:分配一块(system v )共享内存段
参数:
key:ftok(2)的返回值,获取跟key值相关的共享内存段的id
size:指定了共享内存段的大小(系统为其分配页的整数倍)
shmflg:
IPC_CREAT:如果指定了这个标记,如果我的共享内存段不存在就创建一个。
IPC_EXCL:和open(2)一样
mode:指定了共享内存段的权限

返回值:
error:-1 errno被设置
success:共享内存段的ID
举例说明    使用shmget(2)   分配一块共享内存段


shmat(2)
#include <sys/types.h>
#include <sys/shm.h>
void *shmat(int shmid, const void *shmaddr, int shmflg);
功能:关联共享内存段到进程的地址空间
参数:
shmid:指定了共享内存段的id,将这个共享内存段关联到进程空间
shmaddr:NULL,由系统决定共享内存段关联的地址
shmflg:0
返回值:
error (void *) -1返回,errno被设置
success 共享内存段关联到进程的地址



shmdt(2)
int shmdt(const void *shmaddr);
功能:解除共享内存段和当前进程的地址空间的关联
参数:
shmaddr:shmat的返回值,指定了共享内存段在当前进程的指定地址
返回值:
success 0
error -1 errno被设置

通过以下两个程序来演示上述程序:

/*send*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>
int main(void){
    //获取键值
    key_t key = ftok(".",35);
    if(key == -1){
        perror("ftok");
        return -1;
    }
    printf("key:%x\n",key);
    //获取队列ID
    int flag_shm = shmget(key,4096,IPC_CREAT|0644);
    if(flag_shm == -1){
        perror("shmget");
        return -1;
    }
    printf("shmid:%d\n",flag_shm);
    printf("shmger success!\n");
    //关联共享内存段
    void *p_shmat = shmat(flag_shm,NULL,0);
    if(p_shmat == (void *)-1){
        perror("p_shmat");
        return -1;
    }
    //解除关联
    strcpy((char *)p_shmat,"hello kitty!\n");
    getchar();
    shmdt(p_shmat);
}
--------------------------------------------
/*rcv*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>
int main(void){
    //获取键值
    key_t key = ftok(".",35);
    if(key == -1){
        perror("ftok");
        return -1;
    }
    printf("key:%x\n",key);
    //获取队列ID
    int flag_shm = shmget(key,4096,IPC_CREAT|0644);
    if(flag_shm == -1){
        perror("shmget");
        return -1;
    }
    printf("shmid:%d\n",flag_shm);
    printf("shmger success!\n");
    //关联共享内存段
    void *p_shmat = shmat(flag_shm,NULL,0);
    if(p_shmat == (void *)-1){
        perror("p_shmat");
        return -1;
    }
    //解除关联
    printf("%s\n",(char *)p_shmat);
    getchar();
    shmdt(p_shmat);
}

共享内存和消息队列不同,共享内存方式下,读取数据的进程,读取数据之后,并不会移除内存中的数据。

网络基础
网络基础

猜你喜欢

转载自blog.csdn.net/displaymessage/article/details/80328418