虎贲小队程序猿

get along

导航

linux C学习笔记05--信号量与共享内存(进程同步)

花了半天时间把信号量与共享内存整合到了一起,先来看信号量代码,semaphore.c 当中sem_P()和sem_V()函数分别为信号量等待和信号量释放。

两个进程同时访问共享内存,为了避免发生同时读写产生不必要的错误,加入了信号量进行同步。对使用共享内存的区域加上互斥锁,同时只有一个进程能访问共享内存,时其他进程必须等待信号量资源释放后才能继续访问

/*************************************************************************
  > File Name: semaphore.c
  > Author: hailin.ma
  > Mail: mhl2018@126.com 
  > Created Time: Thu 28 May 2015 09:29:35 AM CST
 ************************************************************************/

#include <stdio.h>
#include <sys/ipc.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <errno.h>
#include <sys/sem.h>

#define SEM_KEY 27

 union semun {
     int val;    /* Value for SETVAL */
     struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */
     unsigned short  *array;  /* Array for GETALL, SETALL */
     struct seminfo  *__buf;  /* Buffer for IPC_INFO (Linux-specific) */
 };

int create_semaphore()
{
    int semid;
    union semun sembuf;
    
    sembuf.val = 1;

    if((semid = semget(SEM_KEY,1, IPC_CREAT|IPC_EXCL|0666)) == -1)
    {
        if(errno == EEXIST)
        {
            semid = semget(SEM_KEY,0,0);
            if(semid == -1)
            {
                perror("semget");
                return -1;
            }
            else
            {
                if (semctl(semid,0,SETVAL,sembuf) == -1)
                {
                    perror("semctl");
                    return -1;
                }
                else
                {
                    return semid;
                }
            }

        }
        else
        {
            perror("semget");
            return -1;
        }
    }
    else
    {
        if (semctl(semid,0,SETVAL,sembuf) == -1)
        {
            perror("semctl");
            return -1;
        }
    }

    return semid;
}

int delete_semaphore(int semid)
{
    union semun sembuf;
    if(semctl(semid,0,IPC_RMID,sembuf) == -1)
    {
        perror("delete_semaphore");
        return -1;
    }
}

int sem_P(int semid)
{
    struct sembuf sbuf;
    sbuf.sem_num = 0;
    sbuf.sem_op = -1;
    sbuf.sem_flg = SEM_UNDO;

    if(semop(semid,&sbuf,1) == -1)
    {
        perror("sem_P");
        return -1;
    }
    
    return 0;
}

int sem_V(int semid)
{
    struct sembuf sbuf;
    sbuf.sem_num = 0;
    sbuf.sem_op = 1;
    sbuf.sem_flg = SEM_UNDO;

    if(semop(semid,&sbuf,1) == -1)
    {
        perror("sem_P");
        return -1;
    }    
}

下面是共享内存代码:

/*************************************************************************
    > File Name: share_memory.c
    > Author: hailin.ma
    > Mail: mhl2018@126.com 
    > Created Time: Wed 27 May 2015 11:19:26 PM CST
 ************************************************************************/

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

#define SHARE_MEM_KEY 26
#define MEMORY_SIZE 1000

int create_shm(char **shmptr)
{
    int shmid;

    //if((shmid = shmget(IPC_PRIVATE,200,IPC_CREAT|IPC_EXCL|0666)) == -1)
    if((shmid = shmget(SHARE_MEM_KEY,MEMORY_SIZE,IPC_CREAT|IPC_EXCL|0666)) == -1)
    {
        if(errno == EEXIST)
        {
            shmid = shmget(SHARE_MEM_KEY,0,0);
            if(shmid == -1)
            {
                perror("shmget");
                return -1;
            }
            else
            {
                if((*shmptr = shmat(shmid,0,0666)) == (void*)-1)
                {
                    perror("shmat");
                    return -1;
                }
                else
                {
                    return shmid;
                }
            }
        }
        else
        {    
            perror("shmget");
            return -1;
        }
    }
    
    if((*shmptr = shmat(shmid,0,0)) == (void*)-1)
    {
        perror("shmat");
        return -1;
    }
    
    return shmid;
}

int delete_shm(int shmid,char *shmptr)
{
    shmdt(shmptr);
    if(shmctl(shmid,IPC_RMID,NULL) == -1)
    {
        perror("delete_shm");
        return -1;
    }

    return 0;
}

main函数代码:

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

extern int create_shm(char **shmptr);
extern int create_semaphore();
extern int delete_semaphore();
extern int sem_P(int semid);
extern int sem_V(int semid);
extern int delete_shm(int shmid,char *shmptr);

int main(int argc,char* argv[])
{
    int shmid;
    char *shmptr;
    int semid;

    if((shmid =create_shm(&shmptr)) == -1)
    {
        printf("create_shm error \n");
        return -1;        
    }
    if(argc > 1)
    {
        semid = *(int*)shmptr;        //get semid from share memory

        //this is client
        while(1)
        {
            printf("input str to share memory:");
            sem_P(semid);
            gets(shmptr);
            sem_V(semid);
            if(shmptr[0] == 'q')        //quit
            {
                shmdt(shmptr);            //disconnect to the share memory but will not dellect the memery
                break;
            }
        }
    }
    else
    {
        if((semid = create_semaphore()) == -1)
        {
            perror("main create_semaphore");
            delete_shm(shmid,shmptr);
            return -1;
        }
        *(int*)shmptr = semid;
        printf("share memory is: %d \n",*(int*)shmptr);

        //this is server
        while(1)
        {
            sleep(2);
            sem_P(semid);
            printf("share memory is: %s \n",shmptr);
            sem_V(semid);
            if(shmptr[0] == 'q')
            {
                delete_shm(shmid,shmptr);
                delete_semaphore(semid);
                break;
            }
        }
    }

    printf("into sleeping\n");
    sleep(3);
    printf("out sleeping\n");

    return 0;
}

运行效果图:

 

posted on 2015-05-29 14:31  jjssl  阅读(601)  评论(0编辑  收藏  举报