zoukankan      html  css  js  c++  java
  • Linux进程间通信之《共享内存》入门

    目录

    简述

    代码

    写端代码

    读取端代码

    编译

    运行


    简述

    共享内存是Linux系统进程间通信常用的方式,通常用于数据量较大的情况,如果只是用于不同的进程间消息通知,那不如用消息队列或者socket。之前做的项目中,使用共享内存的其实只有一种情况:视频数据的共享。设备类似于DVR,视频采集编码在一个独立的程序中,另一个程序负责协议通信。

    共享内存要想好用,共享的那段内存,需要用数据结构和队列组织起来,加上读写索引和数据有效标志(已读和未读、可读)。下面的这个示例代码是我初学时的,适合入门和了解使用流程。

    代码

    写端代码

    #include <stdio.h>
    #include <signal.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <sys/ipc.h>
    #include <sys/types.h>
    #include <sys/shm.h>
    #include <string.h>
    #include <unistd.h>
    
    #define N 1024
    
    typedef struct
    {
        pid_t pid;
        char text[N];
    }SHMBUF;
    
    void handler(int signo) {printf("signo=%d
    ", signo);}
    
    int main()
    {
    	int shmid;
        SHMBUF *shmadd;
        key_t key;
        pid_t peerpid;
    
        if ((key = ftok(".", 'a')) == -1)
        {
            perror("ftok");
            exit(-1);
        }
    
        signal(SIGUSR1, handler);
    
    	if ((shmid = shmget(key, sizeof(SHMBUF), 0666 | IPC_CREAT | IPC_EXCL)) == -1)
    	{
            if (errno == EEXIST)
            {
                shmid = shmget(key, sizeof(SHMBUF), 0666);
    	        if ((shmadd = (SHMBUF *)shmat(shmid, NULL, 0)) == (SHMBUF *)-1)
            	{
    	         	perror("shmat");
    		        exit(-1);
            	}
                peerpid = shmadd->pid;
                shmadd->pid = getpid();
                kill(peerpid, SIGUSR1);
            }
            else
            {
        	    perror("shmget");
    	    	exit(-1);
            }
    	}
        else    //first process
        {
    	    if ((shmadd = (SHMBUF *)shmat(shmid, NULL, 0)) == (SHMBUF *)-1)
        	{
    	    	perror("shmat");
    		    exit(-1);
        	}
            shmadd->pid = getpid();
            //sprintf(shmadd, "%d", getpid());
            pause();
            peerpid = shmadd->pid;
        }
    
        printf(">");
        while (1)
        {
            fgets(shmadd->text, N, stdin);
            shmadd->text[strlen(shmadd->text)-1] = '';
            kill(peerpid, SIGUSR1);
            if (strncmp(shmadd->text, "quit", 4) == 0)
            {
                sleep(1);
    	        if (shmdt(shmadd) == -1)
            	{
    		        perror("shmdt");
            	}
    	        if (shmctl(shmid, IPC_RMID, NULL) == -1)
            	{
    		        perror("RM");
            		exit(-1);
            	}
    
                exit(0);
            }
            pause();
            printf(">");
        }
    
    	return 0;
    }
    

    读取端代码

    #include <stdio.h>
    #include <signal.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <sys/ipc.h>
    #include <sys/types.h>
    #include <sys/shm.h>
    #include <string.h>
    #include <unistd.h>
    
    #define N 1024
    
    typedef struct
    {
        pid_t pid;
        char text[N];
    }SHMBUF;
    
    void handler(int signo) {printf("signo=%d
    ", signo);}
    int main()
    {
    	int shmid;
        SHMBUF *shmadd;
        key_t key;
        pid_t peerpid;
    
        if ((key = ftok(".", 'a')) == -1)
        {
            perror("ftok");
            exit(-1);
        }
    
        signal(SIGUSR1, handler);
    
    	if ((shmid = shmget(key, sizeof(SHMBUF), 0666 | IPC_CREAT | IPC_EXCL)) == -1)
    	{
            if (errno == EEXIST)
            {
                shmid = shmget(key, sizeof(SHMBUF), 0666);
    	        if ((shmadd = (SHMBUF *)shmat(shmid, NULL, 0)) == (SHMBUF *)-1)
            	{
    	         	perror("shmat");
    		        exit(-1);
            	}
                peerpid = shmadd->pid;
                shmadd->pid = getpid();
                kill(peerpid, SIGUSR1);
            }
            else
            {
        	    perror("shmget");
    	    	exit(-1);
            }
    	}
        else    //first process
        {
    	    if ((shmadd = (SHMBUF *)shmat(shmid, NULL, 0)) == (SHMBUF *)-1)
        	{
    	    	perror("shmat");
    		    exit(-1);
        	}
            shmadd->pid = getpid();
            pause();
            peerpid = shmadd->pid;
        }
    
        while (1)
        {
            pause();
            printf("read %s
    ", shmadd->text);
            if (strncmp(shmadd->text, "quit", 4) == 0)
            {
    	        if (shmdt(shmadd) == -1)
            	{
    		        perror("shmdt");
            	}
                exit(0);
            }
           // sleep(1);
           usleep(100000);
           kill(peerpid, SIGUSR1);
        }
        exit(0);
    }
    

    编译

    gcc reader.c -o reader
    gcc writer.c -o writer

    运行

  • 相关阅读:
    「AtCoder AGC023F」01 on Tree
    「Wallace 笔记」平面最近点对 解法汇总
    「Codeforces 1181E」A Story of One Country (Easy & Hard)
    「NOI2018」「LOJ #2720」「Luogu P4770」 你的名字
    IdentityServer4设置RefreshTokenExpiration=Sliding不生效的原因
    【知识点】IQueryable.SumAsync方法的NULL异常
    Beyond Compare 4 密钥被吊销
    【知识点】Uri对象的完整地址
    git文件夹大小写问题
    .Net Core学习资料
  • 原文地址:https://www.cnblogs.com/fensnote/p/13436450.html
Copyright © 2011-2022 走看看