system v IPC代码示例

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/rikeyone/article/details/89004349

消息队列

#include <sys/msg.h>
#include <sys/ipc.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

#define pr_debug(fmt,...)   do{ printf("[%ld] DEBUG: "fmt,(long)getpid(),##__VA_ARGS__); fflush(stdout); }while(0)
#define pr_info(fmt,...)    do{ printf("[%ld] INFO:  "fmt,(long)getpid(),##__VA_ARGS__); fflush(stdout); }while(0)
#define pr_err(fmt,...)     do{ printf("[%ld] ERROR: "fmt,(long)getpid(),##__VA_ARGS__); fflush(stdout); }while(0)
#define err_exit(fmt,...)   do{ printf("[%ld] ERROR: "fmt,(long)getpid(),##__VA_ARGS__); exit(1); }while(0)

#define MSQ_MODE 666
#define MIN(a,b) (((a)<(b))?(a):(b))

struct msq_msg {
	long type;
	char data[512];
};

int msq_create(void)
{
	key_t key;
	int msqid;

	key = ftok("/home/xiehaocheng/work/qemu", 1);
	if (key == (key_t)-1) {
		pr_err("ftok error, %s\n", strerror(errno));
		return -1;
	}

	msqid = msgget(key, MSQ_MODE|IPC_CREAT|IPC_EXCL);
	if (msqid < 0) {
		pr_err("msgget error, %s\n", strerror(errno));
		return -1;
	}
	pr_info("msqid:%d\n", msqid);
	return msqid;
}

int msq_create_private(void)
{
	int msqid;

	msqid = msgget(IPC_PRIVATE, MSQ_MODE|IPC_CREAT|IPC_EXCL);
	if (msqid < 0) {
		pr_err("msgget error, %s\n", strerror(errno));
		return -1;
	}
	pr_info("msqid:%d\n", msqid);
	return msqid;
}


int msq_send(int msqid, int type, char *buf, int size)
{
	int ret;
	struct msq_msg msg = {0};
	int nbyte;

	nbyte = MIN(512, size);
	msg.type = type;
	strncpy(msg.data, buf, nbyte);

	do {
		ret = msgsnd(msqid, &msg, nbyte, 0);
		if (ret < 0) {
			if (errno == EINTR) {
				continue;
			} else if (errno == EIDRM) {
				pr_err("msg queue deleted\n");
				return -1;
			} else {
				pr_err("msgsnd error, %s\n", strerror(errno));
				return -1;
			}
		} else if (ret == 0)
			break;
	} while(1);

	return 0;
}

int msq_recv(int msqid, int type, char *buf, int size)
{
	int max = 512, nbyte;
	struct msq_msg msg = {0};

	nbyte = msgrcv(msqid, &msg, max, type, MSG_NOERROR);
	if (nbyte < 0) {
		pr_err("msgrcv error, %s\n", strerror(errno));
		return -1;
	}

	nbyte = MIN(nbyte, size);

	strncpy(buf, msg.data, nbyte);

	return nbyte;
}

int msq_delete(int msqid)
{
	int ret;
	struct msqid_ds msqds;

	ret = msgctl(msqid, IPC_RMID, &msqds);
	if (ret < 0) {
		pr_err("msgctl error\n");
		return -1;
	}
	return 0;
}

int main(int argc, char *argv[])
{
	pid_t pid;
	int msqid;
	char buf[512];

	msqid = msq_create_private();
	if (msqid < 0) {
		err_exit("msq_create error\n");
	}
	if ((pid = fork()) < 0) {
		err_exit("fork error\n");
	} else if (pid > 0) {
		strcpy(buf, "Hello, I'm your parent!\n");
		msq_send(msqid, 1, buf, strlen(buf) + 1);
		usleep(300000);
		msq_recv(msqid, 2, buf, 512);
		pr_info("parent:%s\n", buf);
		wait(NULL);
		msq_delete(msqid);
	} else {
		strcpy(buf, "Hello, I'm your child!\n");
		msq_send(msqid, 2, buf, strlen(buf) + 1);
		usleep(300000);
		msq_recv(msqid, 1, buf, 512);
		pr_info("child:%s\n", buf);
		exit(0);
	}
	return 0;
}

信号量(semaphore)

/*
 *
 *	id = sema_create(key, initval);	# create with initial value
 *	id = sema_open(key);		# open (must already exist)
 *	sema_down(id);			# P = down by 1
 *	sema_up(id);				# V = up by 1
 *	sema_close(id);			# close
 *
 *  Define two semaphores in the semaphore set:
 *
 *  sem[0]: this semaphore is for normal use, down and up is operated
 *  on this semaphore.
 * 
 *  sem[1]: trace for the processes which using this semaphore set, so we
 *  can delete the semaphore when no one is using it. Why do it like this? 
 *  Because we want to handle the semaphore set by the program itself, so 
 *  we don't  need to clean it by "ipcrm" command or some way like it.
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <errno.h>

#define pr_debug(fmt,...)   do{ printf("[%ld] DEBUG: "fmt,(long)getpid(),##__VA_ARGS__); fflush(stdout); }while(0)
#define pr_info(fmt,...)    do{ printf("[%ld] INFO:  "fmt,(long)getpid(),##__VA_ARGS__); fflush(stdout); }while(0)
#define pr_err(fmt,...)     do{ printf("[%ld] ERROR: "fmt,(long)getpid(),##__VA_ARGS__); fflush(stdout); }while(0)
#define err_exit(fmt,...)   do{ printf("[%ld] ERROR: "fmt,(long)getpid(),##__VA_ARGS__); exit(1); }while(0)

/*
 * system call:
 *  - semget
 *  - semctl
 *  - semop
 */

/* initial value of process counter */
#define	PROCESS_COUNT	10000
#define SEMA_KEY 0x65539

void sema_destory(int id)
{
	/* delete this semaphore set */
	if (semctl(id, 0, IPC_RMID, 0) < 0) {
		pr_err("can't IPC_RMID, %s\n", strerror(errno));
	}
	pr_info("sema destoryed!\n");
}

int sema_create(key_t key, int initval)
{
	int		id;
	union semun {
		int		val;
		struct semid_ds	*buf;
		unsigned short		*array;
	} semctl_arg;
	struct sembuf	op[1] = {
		{1, -1, SEM_UNDO}
	};

	if (key == IPC_PRIVATE)
		return -1;	/* not intended for private semaphores */

	else if (key == (key_t) -1)
		return -1;	/* probably an ftok() error by caller */

	if ((id = semget(key, 2, 0666 | IPC_CREAT)) < 0)
		return -1;	/* permission problem or tables full */


	/* init sem[0] to the init value */
	semctl_arg.val = initval;
	if (semctl(id, 0, SETVAL, semctl_arg) < 0) {
		pr_err("can SETVAL[0]\n");
		goto err_out;
	}
	
	/* set sem[1] to max process count */
	semctl_arg.val = PROCESS_COUNT;
	if (semctl(id, 1, SETVAL, semctl_arg) < 0) {
		pr_err("can SETVAL[1]\n");
		goto err_out;
	}

	/* TODO: SHOULD LOCK */
	/*
	 * should decrease sem[1], DOWN when open 
	 */
	if (semop(id, op, 1) < 0) {
		pr_err("can't semop\n");
		goto err_out;
	}
	/* TODO: SHOULD UNLOCK */

	return id;

err_out:
	/* delete this semaphore set */
	sema_destory(id);
	return -1;
}

int sema_open(key_t key)
{
	int	id;
	struct sembuf	op[1] = {
		{1, -1, SEM_UNDO}
	};

	if (key == IPC_PRIVATE)
		return(-1);	/* not intended for private semaphores */

	else if (key == (key_t) -1)
		return(-1);	/* probably an ftok() error by caller */

	if ((id = semget(key, 2, 0)) < 0)
		return(-1);	/* doesn't exist, or tables full */

	/* TODO: SHOULD LOCK */

	/*
	 * should decrease sem[1], DOWN when open 
	 */
	if (semop(id, op, 1) < 0) {
		pr_err("can't semop\n");
		return -1;
	}
	/* TODO: SHOULD UNLOCK */
	return(id);
}


void sema_close(int id)
{
	register int	semval;
	struct sembuf	op[1] = {
		{1, 1, SEM_UNDO}	
	};

	/* TODO: SHOULD LOCK */

	/*
	 * should increase sem[1], UP when close
	 */
	if (semop(id, op, 1) < 0) {
		err_exit("can't semop\n");
	}

	if ((semval = semctl(id, 1, GETVAL, 0)) < 0)
		err_exit("can't GETVAL\n");

	if (semval > PROCESS_COUNT) 	/* exception: this should not happen */
		err_exit("sem[1] > 10000\n");
	else if (semval == PROCESS_COUNT) /* no process holding this semaphore set, so destory it */
		sema_destory(id);
	else
		pr_info("still have process hold the semaphore!!! Don't destory!\n");

	/* TODO: SHOULD UNLOCK */
}

static int sema_op(int id, int value)
{
	struct sembuf	op[1] = {
		{0, 99, SEM_UNDO}	
	};

	if (value == 0) {
		pr_err("can't have value 0\n");
		return -1;
	}

	op[0].sem_op = value;

	if (semop(id, op, 1) < 0) {
		pr_err("sem_op error\n");
		return -1;
	}
	return 0;
}

/*
 *  DOWN operation.
 */

void sema_down(int id)
{
	sema_op(id, -1);
}

/*
 *  UP operation.
 */

void sema_up(int id)
{
	sema_op(id, 1);
}

int main(int argc, char argv[])
{
	pid_t pid;
	int id;

	if ((pid = fork()) < 0)
		err_exit("fork error\n");
	else if (pid > 0) {
		id = sema_create(SEMA_KEY, 1);
		if (id < 0)
			exit(1);
		pr_info("parent get semaphore\n");
		sema_down(id);
		sleep(5);
		pr_info("parent put semaphore\n");
		sema_up(id);
		sema_close(id);
		wait(NULL);
	} else {
		sleep(1);
		id = sema_open(SEMA_KEY);
		pr_info("child wait for sema\n");
		sema_down(id);
		pr_info("child get sema\n");
		sema_up(id);
		pr_info("child put sema\n");
		sema_close(id);
	}
	return 0;
}

共享内存

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

#define pr_debug(fmt,...)   do{ printf("[%ld] DEBUG: "fmt,(long)getpid(),##__VA_ARGS__); fflush(stdout); }while(0)
#define pr_info(fmt,...)    do{ printf("[%ld] INFO:  "fmt,(long)getpid(),##__VA_ARGS__); fflush(stdout); }while(0)
#define pr_err(fmt,...)     do{ printf("[%ld] ERROR: "fmt,(long)getpid(),##__VA_ARGS__); fflush(stdout); }while(0)
#define err_exit(fmt,...)   do{ printf("[%ld] ERROR: "fmt,(long)getpid(),##__VA_ARGS__); exit(1); }while(0)

#define	ARRAY_SIZE	40000
#define	MALLOC_SIZE	100000
#define	SHM_SIZE	100000
#define	SHM_MODE	0600	/* user read/write */

char	array[ARRAY_SIZE];

int
main(void)
{
	int		shmid;
	char	*ptr, *shmptr;

	pr_info("array[] from %p to %p\n", (void *)&array[0],(void *)&array[ARRAY_SIZE]);
	pr_info("stack around %p\n", (void *)&shmid);

	if ((ptr = malloc(MALLOC_SIZE)) == NULL)
		err_exit("malloc error");

	pr_info("malloced from %p to %p\n", (void *)ptr, (void *)ptr+MALLOC_SIZE);

	if ((shmid = shmget(IPC_PRIVATE, SHM_SIZE, SHM_MODE)) < 0)
		err_exit("shmget error");

	if ((shmptr = shmat(shmid, 0, 0)) == (void *)-1)
		err_exit("shmat error");

	pr_info("shared memory attached from %p to %p\n", (void *)shmptr, (void *)shmptr+SHM_SIZE);

	if (shmctl(shmid, IPC_RMID, 0) < 0)
		err_exit("shmctl error");

	exit(0);
}

猜你喜欢

转载自blog.csdn.net/rikeyone/article/details/89004349
今日推荐