您的位置:首页 > 运维架构 > Linux

<转>linux操作系统编程——共享内存读写(采用信号量进行同步互斥)

2013-09-23 10:38 537 查看
/article/1409902.html

程序要求:

创建一个写端和一个读端,写端写入数据后读端才开始读,读端读完数据后,写端才可以开始写,这样的同步采用信号机制实现,并且写端与读端打开顺序不同也能实现功能;

程序如下:

(1)write.c(写端)

[cpp] view plaincopyprint?

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/shm.h>

#include <errno.h>

#include "sem.h"

typedef struct

{

char buf[1024];

}memory;

int main(int argc, const char *argv[])

{

key_t key;

memory *p = NULL;

int shmid;

int create_flag = 0;

int sem_id;

if ((key = ftok(".", 'a')) < 0)

{

perror("failed to get key");

exit(-1);

}

if ((sem_id = semget(key, 1, 0666 | IPC_CREAT | IPC_EXCL)) < 0)

{

if (errno == EEXIST)

{

if ((sem_id = semget(key, 1, 0666)) < 0)

{

perror("failed to semget");

exit(-1);

}

}

}

init_sem(sem_id, 0);

if ((shmid = shmget(key, sizeof(memory), 0666 | IPC_CREAT | IPC_EXCL)) < 0)

{

if (errno == EEXIST)

{

if ((shmid = shmget(key, sizeof(memory), 0666)) < 0)

{

perror("failed to shmget memory");

exit(-1);

}

}

else

{

perror("failed to shmget");

exit(-1);

}

}

else

create_flag = 1;

if ((p = shmat(shmid, NULL, 0)) == (void *)(-1))

{

perror("failed to shmat memory");

exit(-1);

}

while(1)

{

printf(">");

fgets(p->buf, sizeof(p->buf), stdin);

p->buf[strlen(p->buf) - 1] = 0;

sem_v(sem_id);

if (strncmp(p->buf, "quit", 4) == 0)

break;

}

if (create_flag == 1)

{

if (shmdt(p) < 0)

{

perror("failed to shmdt memory");

exit(-1);

}

if (shmctl(shmid, IPC_RMID, NULL) == -1)

{

perror("failed to delete share memory");

exit(-1);

}

delete_sem(sem_id);

}

return 0;

}

(2)read.c(读端)

[cpp] view plaincopyprint?

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/shm.h>

#include <errno.h>

#include "sem.h"

typedef struct

{

char buf[1024];

}memory;

int main(int argc, const char *argv[])

{

key_t key;

int shmid;

memory *p = NULL;

int create_flag = 0;

int sem_id;

if ((key = ftok(".", 'a')) < 0)

{

perror("failed to get key");

exit(-1);

}

if ((sem_id = semget(key, 1, 0666 | IPC_CREAT | IPC_EXCL)) < 0)

{

if (errno == EEXIST)

{

if ((sem_id = semget(key, 1, 0666)) < 0)

{

perror("failed to semget");

exit(-1);

}

}

}

init_sem(sem_id, 0);

if ((shmid = shmget(key, sizeof(memory), 0666 | IPC_CREAT | IPC_EXCL)) < 0)

{

if (errno == EEXIST)

{

if ((shmid = shmget(key, sizeof(memory), 0666)) < 0)

{

perror("failed to create share memory");

exit(-1);

}

}

else

{

perror("failed to shmget");

exit(-1);

}

}

else

create_flag = 1;

if ((p = shmat(shmid, NULL, 0)) == (void *)(-1))

{

perror("failed to shmat");

exit(-1);

}

while(1)

{

sem_p(sem_id);

if (strncmp(p->buf, "quit", 4) == 0)

break;

printf("recv: %s\n", p->buf);

}

if (create_flag == 1)

{

if (shmdt(p) < 0)

{

perror("failed to shmdt");

exit(-1);

}

if (shmctl(shmid, IPC_RMID, NULL) == -1)

{

perror("failed to delete share memory");

exit(-1);

}

delete_sem(sem_id);

}

return 0;

}

关于封装信号量函数的头文件:

[cpp] view plaincopyprint?

#include <stdio.h>

#include <stdlib.h>

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/sem.h>

#include <unistd.h>

void init_sem(int , int );

void delete_sem(int );

void sem_p(int );

void sem_v(int );

union semun

{

int val;

struct semid_ds *buf;

unsigned short *array;

};

void init_sem(int sem_id, int init_value)

{

union semun sem_union;

sem_union.val = init_value;

if (semctl(sem_id, 0, SETVAL, sem_union) < 0)

{

perror("failed to init_sem");

exit(-1);

}

return ;

}

void delete_sem(int sem_id)

{

union semun sem_union;

if (semctl(sem_id, 0, IPC_RMID, sem_union) < 0)

{

perror("failed to delete_sem");

exit(-1);

}

return ;

}

void sem_p(int sem_id)

{

struct sembuf sem_b;

sem_b.sem_num = 0;

sem_b.sem_op = -1;

sem_b.sem_flg = SEM_UNDO;

if (semop(sem_id, &sem_b, 1) < 0)

{

perror("failed to sem_p");

exit(-1);

}

return;

}

void sem_v(int sem_id)

{

struct sembuf sem_b;

sem_b.sem_num = 0;

sem_b.sem_op = 1;

sem_b.sem_flg = SEM_UNDO;

if (semop(sem_id, &sem_b, 1) < 0)

{

perror("failed to sem_v");

exit(-1);

}

return ;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: