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

Linux共享内存示例,使用信号量同步

2015-11-26 16:42 681 查看
1、shm_test1.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stddef.h>
#include <errno.h>
#include <sys/un.h>
#include <sys/types.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/socket.h>

#define SEM_KEY     100
#define SHM_KEY     101
#define TOTAL_SEM   10
#define UNIX_DOMAIN "/tmp/unix_sock"

typedef struct shared_use {
int pktlen;
unsigned char pkt[1528];
} shared_use_t;

static unsigned char ucast_pkt[] = {
0x00, 0xd0, 0xf8, 0x00, 0x99, 0x22, 0x00, 0x00,
0x00, 0x01, 0x01, 0x07, 0x08, 0x06, 0x00, 0x01,
0x08, 0x00, 0x06, 0x04, 0x00, 0x01, 0xbc, 0x30,
0x00, 0x00, 0x00, 0x01, 0x01, 0x07, 0xc0, 0xa8,
0xcc, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xc0, 0xa8, 0xcc, 0x64
4000
, 0x01, 0x02, 0x03, 0x04,
0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14};

static int sem_id = 0;
static int com_fd = 0;
static void *shm = NULL;

/* 获取信号量资源 */
static int semaphore_v(void)
{
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) == -1) {
return -1;
}

return 0;
}

/* 释放信号量资源 */
static int semaphore_p(void)
{
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) == -1) {
return -1;
}

return 0;
}

/* 初始化信号量 */
static int semaphore_init(void)
{
union semun sem_union;

sem_id = semget((key_t)SEM_KEY, 1, 0666 | IPC_CREAT);
if (sem_id == -1) {
return -1;
}

sem_union.val = 1;
if (semctl(sem_id, 0, SETVAL, sem_union) == -1) {
return -1;
}

return 0;
}

/* 初始化共享内存 */
static int sharemmy_init(void)
{
int shmid;

/* 创建共享内存区域块 */
shmid = shmget((key_t)SHM_KEY, sizeof(shared_use_t), 0666 | IPC_CREAT);
if (shmid == -1) {
return shmid;
}

/* 将本进程的虚拟内存映射到共享内存 */
shm = shmat(shmid, (void *)0, 0);
if (shm == (void *)-1) {
return -1;
}

return shmid;
}

static int sharemmy_destroy(int shmid, void *shm)
{
int rv;

/* 删除本进程与共享内存的映射 */
rv = shmdt(shm);
if (rv == -1) {
return rv;
}

/* 删除创建的共享内存块 */
rv = shmctl(shmid, IPC_RMID, 0);
if (rv == -1) {
return rv;
}

return 0;
}

static int domain_server(void)
{
int rv;
int listen_fd;
socklen_t len;
struct sockaddr_un srv_un;
struct sockaddr_un clt_un;

listen_fd = socket(PF_UNIX, SOCK_STREAM, 0);
if (listen_fd < 0) {
perror("socket: ");
return -1;
}

memset(&srv_un, 0, sizeof(srv_un));
srv_un.sun_family = AF_UNIX;
strncpy(srv_un.sun_path, UNIX_DOMAIN, sizeof(srv_un.sun_path) - 1);
unlink(UNIX_DOMAIN);
rv = bind(listen_fd, (struct sockaddr *)&srv_un, sizeof(srv_un));
if (rv < 0) {
perror("bind: ");
close(listen_fd);
unlink(UNIX_DOMAIN);
return -1;
}

rv = listen(listen_fd, 1);
if (rv < 0) {
perror("listen: ");
close(listen_fd);
unlink(UNIX_DOMAIN);
return -1;
}

len = sizeof(clt_un);
while (1) {
com_fd = accept(listen_fd, (struct sockaddr *)&clt_un, &len);
if (errno == EINTR && com_fd == -1) {
continue;
}
break;
}

return 0;
}

static void print_cmd_help(void)
{
printf("CAMMAND NOT SUPPORT!.\n");
printf("********** Help Info **********\n");
printf("  1. Send -------- send a packet to commad.\n");
printf("  2. Quit -------- quit the program.\n");
printf("**********    End    **********\n");
}

static int shmwrite(void *shm)
{
int rv;
shared_use_t *shared;

rv = semaphore_p();
if (rv < 0) {
return -1;
}

shared = (shared_use_t *)shm;
shared->pktlen = sizeof(ucast_pkt);
memcpy(shared->pkt, ucast_pkt, sizeof(ucast_pkt));

rv = semaphore_v();
if (rv < 0) {
return -1;
}

return 0;
}

int main()
{
int rv;
int shmid;
char cmd[10];

rv = semaphore_init();
if (rv < 0) {
printf("Init a semaphore fail.\n");
return 0;
}

shmid = sharemmy_init();
if (shmid == -1) {
printf("Init a share memory fail.\n");
return 0;
}

rv = domain_server();
if (rv < 0) {
printf("Create domain server socket fail.\n");
return 0;
}
printf("Server init success!\n");
printf("\n");

while (1) {
memset(cmd, 0, sizeof(cmd));
printf("Enter a command:");
scanf("%s", cmd);
if (cmd[9] != 0) {
printf("Error : Command is too long, at most 9 char allowed!!!\n");
continue;
} else if (strstr(cmd, "send") != NULL || strstr(cmd, "Send") != NULL) {
rv = shmwrite(shm);
if (rv < 0) {
printf("Write packet to share memory fail.\n");
break;
}
rv = send(com_fd, cmd, sizeof(cmd), 0);
if (rv < 0) {
printf("Send command send fail.\n");
continue;
}
} else if (strstr(cmd, "quit") != NULL || strstr(cmd, "Quit") != NULL) {
printf("**********Stop Send Packet To Client.***********\n");
rv = send(com_fd, cmd, sizeof(cmd), 0);
if (rv < 0) {
printf("Quit commadn send fail.\n");
}
break;
} else {
print_cmd_help();
}
printf("\n");
}

usleep(1000);
rv = sharemmy_destroy(shmid, shm);
if (rv < 0) {
printf("Destroy share memory fail.\n");
return 0;
}

return 1;
}


2、shm_test2.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/un.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <sys/sem.h>
#include <sys/stat.h>
#include <sys/socket.h>

#define SEM_KEY     100
#define PRINT_TIMES 10
#define SHM_KEY     101
#define UNIX_DOMAIN "/tmp/unix_sock"

typedef struct shared_use {
int pktlen;
unsigned char pkt[1528];
} shared_use_t;

static int sem_id = 0;
static int connect_fd = 0;
static void *shm = NULL;

static int semaphore_v()
{
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) ==
b0f5
-1) {
return -1;
}

return 0;
}

static int semaphore_p()
{
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) == -1) {
return -1;
}

return 0;
}

static int semaphore_init()
{
sem_id = semget((key_t)SEM_KEY, 0, 0666 | IPC_CREAT);
if (sem_id == -1) {
return -1;
}

return 0;
}

static int sharemmy_init(void)
{
int shmid;

shmid = shmget((key_t)SHM_KEY, sizeof(shared_use_t), 0666 | IPC_CREAT);
if (shmid == -1) {
return shmid;
}

shm = shmat(shmid, (void *)0, 0);
if (shm == (void *)-1) {
return -1;
}

return shmid;
}

static int sharemmy_destroy(int shmid, void *shm)
{
int rv;

rv = shmdt(shm);
if (rv == -1) {
return rv;
}

return 0;
}

static int domain_client(void)
{
int rv;
struct sockaddr_un srv_un;

connect_fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (connect_fd < 0) {
perror("client socket: ");
return -1;
}

memset(&srv_un, 0, sizeof(srv_un));
srv_un.sun_family = AF_UNIX;
strncpy(srv_un.sun_path, UNIX_DOMAIN, sizeof(srv_un.sun_path) - 1);
rv = connect(connect_fd, (struct sockaddr *)&srv_un, sizeof(srv_un));
if (rv < 0) {
perror("connect: ");
close(connect_fd);
return -1;
}

return 0;
}

static int shmread(shared_use_t *shared)
{
int rv;

rv = semaphore_p();
if (rv < 0) {
return -1;
}

shared->pktlen = ((shared_use_t *)shm)->pktlen;
memcpy(shared->pkt, ((shared_use_t *)shm)->pkt, shared->pktlen);

rv = semaphore_v();
if (rv < 0) {
return -1;
}

return 0;
}

static void print_pkt(shared_use_t shared_pkt)
{
int i;

printf("********** RECV PACKET **********\n");
for (i = 0; i < shared_pkt.pktlen; i++) {
printf("0x%02x ", shared_pkt.pkt[i]);
if ((i + 1) % 16 == 0) {
printf("\n");
}
}
printf("**********     END     **********\n");
printf("\n");
}

int main()
{
int rv;
int shmid;
char cmd[10];
shared_use_t shared_pkt;

rv = semaphore_init();
if (rv < 0) {
printf("Init a semaphore fail.\n");
}

shmid = sharemmy_init();
if (shmid == -1) {
printf("Init a share memory fail.\n");
return 0;
}

usleep(10*1000);
rv = domain_client();
if (rv < 0) {
printf("Create domain client socket fail.\n");
return 0;
}
printf("Client init success.\n");

while (1) {
memset(cmd, 0, 10);
rv = recv(connect_fd, cmd, sizeof(cmd), 0);
if (rv < 0) {
printf("Recv cmd from server fail.\n");
close(connect_fd);
break;
}
if (strstr(cmd, "send") != NULL || strstr(cmd, "Send") != NULL) {
rv = shmread(&shared_pkt);
if (rv < 0) {
printf("Read packet from share memory fail.\n");
break;
}
print_pkt(shared_pkt);
continue;
} else if (strstr(cmd, "quit") != NULL || strstr(cmd, "Quit") != NULL) {
printf("Quit the packet recv client.\n");
break;
} else {
printf("Unrecognized command for client.\n");
break;
}
}

rv = sharemmy_destroy(shmid, shm);
if (rv < 0) {
printf("Destroy share memory fail.\n");
return 0;
}
close(connect_fd);

return 1;
}


以上两个程序实现的功能:shm_test1接收用户输入命令,如果是send则将向共享内存区域写入一个报文,并发送socket消息通知进程shm_test2从共享内存中读出报文并打印出来。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: