• 管道,消息队列,共享内存!


    2015.1.26
    星期一,阴天

    linux中使用的较多的进程通信方式主要有一下几种:
    1.管道(Pipe):管道可用于具有亲缘关系进程间的通信,有名管道,除了具有管道所具有功能外,它
    还允许无亲缘关系进程的通信
    2.信号(signal):信号是在软件层次上对中断机制的一种模拟,它是比较复杂的通信方式,用于通知进程
    有某事发生,一个进程收到一个信号与处理器收到一个中断请求效果上可以说是一样的
    3.消息队列:(Messge Queue):消息队列是消息的连接表,包括Posix消息队列SystemV消息队列,它克服了前两种通信方式中信息量有限的
    的缺点,具有写权限的进程可以按照一定的规划向消息队列中添加新的消息,对消息队列有读权限的进程则可以从
    消息队列中读取消息
    4.共享内存(Shared memory):可以说这是最有用的进程通信方式,它使得多个进程可以访问同一块内存空间,
    不同进程可以及时看到对方进程中对共享内存中数据的更新,这种通信方式需要依靠某种同步机制,如互斥锁和信号量等
    5.信号量(Semaphore):主要作为进程之间以及同一进程的不同线程之间的同步和互斥手段
    5.套接字(Socket):这是一种更为一般的进程通信机制,他是可用于网络中不同机器之间的进程通信,应用非常广泛,

    1.管道系统的调用:
    管道是基于文件描述符的通信方式,当一个管道建立时,他会创建两个文件描述符fds[0](固定用于读管道),fds[1](固定用于写管道)
    管道关闭时只需要将这两个文件描述符关闭即可,可以使用普通的close()函数逐个关闭各个文件描述符

    2.管道创建函数
    int pipe(int fd[2]) 成功:0,出错:-1

    5.管道读写注意点
    1.只有在管道的读端存在时,向管道写入数据才有意义,否则,向管道写入数据的进程将收到内核传来的
    SIGPIPE信号(通常为Broken pipe错误)
    2.向管道写入数据时,linux将不保证写入的原子性,管道缓冲区有空闲区域,写进程就会试图向管道写入数据,如
    果读进程不读取管道缓冲区中的数据,那么写操作将会一直阻塞。
    3.父子进程在运行时,他们的先后次序并不能保证,因此,在这里为了保证父子进程已经关闭了相应的
    文件描述符,可在两个进程中调用sleep()函数,但这不是很好的方法,,可参考进程同步和互斥机制

    下面是今天分析的一些程序:

    消息队列的发送和写入程序:

    #include <sys/types.h>
    #include <sys/msg.h>
    #include <unistd.h>

    struct msg_buf
    {
    int mtype;
    char data[255];
    };

    int main()
    {
    key_t key;
    int msgid;
    int ret;
    struct msg_buf msgbut;

    key = ftok("/tmp/2",'a'); 获得键值
    printf("key = [%x] ",key);
    msgid = msgget(key,IPC_CRREAT|0666);

    if(msgid == -1)
    {
    printf("create error ");
    return -1;
    }

    msgbuf.mtype = getpid();
    strcpy(msgbuf.data,"test haha");
    ret = msgsnd(msgid,&msgbuf,sizeof(msgbuf.data),IPC_NOWAIT); 发送信息
    if(ret == -1)
    {
    printf("send message err ");
    return -1;
    }

    memset(&msgbuf,0,sizeof(msgbuf));
    ret = msgrcv(msgid,&msgbuf,sizeof(msgbuf.data),getpid(),IPC_NOWAIT); 读取信息
    if (ret==-1)
    {
    printf("recv message err ");
    return -1;
    }

    printf("recv msg = [%s] ",msgbuf.data);
    }

    共享内存的一段程序:

    #include <stdio.h>
    #include <signal.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <unistd.h>
    #include <sys/stat.h>
    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/shm.h>

    #define PERM S_IRUSR|S_IWUSR

    int main(int argc, char **argv)
    {
    int shmid;
    char *p_addr,*c_addr;

    if(argc != 2)
    {
    fprintf(stderr,"usage:%s a",argv[0]);
    exit(1);
    }

    if((shmid = shmget(IPC_PRIVATE,1024,PERM)) == -1)
    {
    fprintf(stderr,"Create share Memory error:%s a",strerror(errno));
    exit(1);
    }

    if(fork())
    {
    p_addr = shmat(shmid ,0, 0);
    memset(p_addr,'',1024);
    strncpy(p_addr,argv[1],1024);
    wait(NULL);
    exit(0);

    }
    else
    {
    sleep(1);
    c_addr = shmat(shmid, 0, 0);
    printf("client get %s ",c_addr);
    exit(0);
    }

    }

    今天老师没有上课,上午和班级同学分享了以前做光立方的那段经历,讲了半个小时吧,好多想表达的意思没表达出来,
    这是一个弱点,另一方法也反映自己有写只是掌握的不是很牢固,需要继续学习。整理了上个星期老师上课的知识点,统计
    了一下同学们不怎么明白的一些知识点,然后交给了老师,上午很快就结束了。做的事不多,但是到讲台上锻炼了一下自己
    的表达能力。下午看了四个视频,都是关于进程通信的,包括管道和共享内存,程序基本能懂,还需要联系,现在我们的课程还
    没上到这里,没有资料书,看PDF不好查函数的用法,上下找很麻烦。回去借点书看,明天我想看ARM的基础知识了!

    **********************************************************************************************************************************************************
    **********************************************************************************************************************************************************
    **********************************************************************************************************************************************************

  • 相关阅读:
    错误记录(一):VSCode
    【洛谷P4770】你的名字
    【洛谷P3177】树上染色
    【洛谷P3704】数字表格
    【CF762F】Tree nesting
    【洛谷P5064】等这场战争结束之后
    【洛谷P3346】诸神眷顾的幻想乡
    【BZOJ#2119】股市的预测
    UiPath数据抓取Data Scraping的介绍和使用
    UiPath录制器的介绍和使用
  • 原文地址:https://www.cnblogs.com/cnlg/p/4251618.html
Copyright © 2020-2023  润新知