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

    运行

  • 相关阅读:
    带有“全选”的combotree
    combotree(组合树)的使用
    根据权限显示accordion
    accordion(折叠面板)的使用
    js中substr、substring、indexOf、lastIndexOf的用法
    EasyUI中使用自定义的icon图标
    EasyUI tree的三种选中状态
    C# List集合去重使用lambda表达式
    C# DataTable去重,根据列名去重保留其他列
    win10下部署.Net Web项目到IIS10
  • 原文地址:https://www.cnblogs.com/fensnote/p/13436450.html
Copyright © 2011-2022 走看看