版权声明:本文为博主原创文章,未经博主允许不得转载。 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);
}