linux编程---进程间通信---共享内存

来源:互联网 发布:pdf批量合并软件 编辑:程序博客网 时间:2024/06/06 07:34

共享内存进程间通信机制主要用于实现进程间大量的数据传输。


1  创建共享内存

  #include <sys/ipc.h>
  #include <sys/shm.h>

  int shmget(key_t key, size_t size, int shmflg);


2  共享内存控制

 int shmctl(int shmid, int cmd, struct shmid_ds *buf);


3  映射共享内存对象

void *shmat(int shmid, const void *shmaddr, int shmflg);


4分离共享内存对象

int shmdt(const void *shmaddr);


实例一

父子进程通过共享内存通信

#include<errno.h>
#include<fcntl.h>
#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<sys/shm.h>
#include<sys/wait.h>
#include<stdlib.h>

int main(int argc,char* argv[])
{
    int childpid;
    int id;
    int i;
    int buf[10];
    char* ptr;
    int totalbytes = 0;
    key_t key;
    key = ftok("tmp",3);    

    if((childpid = fork()) == -1)
    {
        perror("fork");
        exit(EXIT_FAILURE);
    }    
    if(childpid == 0)
    {
        //notice permission
        if((id = shmget(key,20*sizeof(char),0666|IPC_CREAT)) == -1)
        {
            perror("failed to create shared memory segment");
            exit(EXIT_FAILURE);
        }
        if((ptr = (char*)shmat(id,0,0)) == NULL)
        {
            if(shmctl(id,IPC_RMID,NULL) == -1)
                perror("failed to remove memory segment");
                exit(EXIT_FAILURE);
        }
        for(i=0;argv[1][i]!='\0';i++)
        {
            *ptr = argv[1][i];
            ptr++;
        }
        printf("this is child.\nwrite argv[1] to shm.\nyou input charater count is %d\n",i);
        exit(EXIT_SUCCESS);
    }

    
    else
    {
        wait(NULL);
        if((id = shmget(key,10*sizeof(char),0666|IPC_CREAT)) == -1)
        {
            perror("shmget");
            exit(EXIT_FAILURE);
        }
        if((ptr = (char*)shmat(id,0,0)) == NULL)
        {
            perror("shmat");
            if(shmctl(id,IPC_RMID,NULL) == -1)
                perror("failed to remove memory segment");
                exit(EXIT_FAILURE);
        }
        printf("this is parent.\ninput character is %s\n",ptr);
        if(shmctl(id,IPC_RMID,NULL) == -1)
        {
                perror("failed to remove memory segment");
                exit(EXIT_FAILURE);
        }
        exit(EXIT_SUCCESS);
    }
}

实例二

两个进程通过共享内存通信

同时,使用信号量来保证两个进程的读写同步。

发送方程序如下

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/shm.h>
#include<sys/ipc.h>
#include<sys/sem.h>
#include<string.h>


int main(int argc,char* argv[])
{
        int running = 1;
        int shid;
        int semid;
        int value;
        void *sharem = NULL;

        struct sembuf  sem_b;
        sem_b.sem_num = 0;
        sem_b.sem_flg = SEM_UNDO;

        key_t key;
        key = ftok("tmp",3);

        if((semid = semget(key,1,0666|IPC_CREAT)) == -1)
        {
                perror("semget");
                exit(EXIT_FAILURE);
        }
        if(semctl(semid,0,SETVAL,0) == -1)
        {
                printf("sem init error");
                if(semctl(semid,0,IPC_RMID,0) != 0)
                {
                        perror("semctl");
                        exit(EXIT_FAILURE);
                }
                exit(EXIT_FAILURE);
        }
        key_t key1;
        key1 = ftok("tmp2",4);
        shid = shmget(key1,10*sizeof(char),0600|IPC_CREAT);
        if(shid == -1)
        {
                        perror("shmget");
                        exit(EXIT_FAILURE);
        }
        sharem = shmat(shid,NULL,0);
        if(sharem == NULL)
        {
                        perror("shmat");
                        exit(EXIT_FAILURE);
        }
        while(running)
        {
                if((value = semctl(semid,0,GETVAL)) == 0)
                {
                        printf("write data operate\n");
                        printf("please input charater:");
                        scanf("%s",sharem);
                        sem_b.sem_op = 1;
                        if(semop(semid,&sem_b,1) == -1)
                        {
                                fprintf(stderr,"semaphore_p failed\n");
                                exit(EXIT_FAILURE);
                        }
                }
                if(strcmp(sharem,"end") == 0)
                        running--;
        }
        shmdt(sharem);

        return 0;
}

接收方程序如下

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/shm.h>
#include<sys/ipc.h>
#include<sys/sem.h>
#include<string.h>


int main(int argc,char* argv[])
{
        int running = 1;
        int shid;
        int semid;
        int value;
        void *sharem = NULL;

        struct sembuf  sem_b;
        sem_b.sem_num = 0;
        sem_b.sem_flg = SEM_UNDO;

        key_t key;
        key = ftok("tmp",3);

        if((semid = semget(key,1,0666|IPC_CREAT)) == -1)
        {
                perror("semget");
                exit(EXIT_FAILURE);
        }
        if(semctl(semid,0,SETVAL,0) == -1)
        {
                printf("sem init error");
                if(semctl(semid,0,IPC_RMID,0) != 0)
                {
                        perror("semctl");
                        exit(EXIT_FAILURE);
                }
                exit(EXIT_FAILURE);
        }
        key_t key1;
        key1 = ftok("tmp2",4);
        shid = shmget(key1,10*sizeof(char),0600|IPC_CREAT);
        if(shid == -1)
        {
                        perror("shmget");
                        exit(EXIT_FAILURE);
        }
        sharem = shmat(shid,NULL,0);
        if(sharem == NULL)
        {
                        perror("shmat");
                        exit(EXIT_FAILURE);
        }
        while(running)
        {
                if((value = semctl(semid,0,GETVAL)) == 1)
                {
                        printf("read data operate\n");
                        sem_b.sem_op = -1;
                        if(semop(semid,&sem_b,1) == -1)
                        {
                                fprintf(stderr,"semaphore_p failed\n");
                                exit(EXIT_FAILURE);
                        }
                        printf("%s\n",sharem);
                }
                if(strcmp(sharem,"end") == 0)
                        running--;
        }
        shmdt(sharem);

        if(shmctl(shid,IPC_RMID,0) != 0)
        {
                        perror("shctl");
                        exit(EXIT_FAILURE);
        }

        if(semctl(semid,IPC_RMID,0) != 0)
        {
                        perror("semctl");
                        exit(EXIT_FAILURE);
        }

        return 0;
}



原创粉丝点击