unix网络编程【13章 posix共享内存区】 中实现了一个简单的日志服务,使用共享内存实现了没有亲缘关系的进程间的通信。这个共享内存是采用内存映射文件的(用shm_open),匿名的共享内存实现有亲缘关系进程间的通信比较方便,没有亲缘关系的就不知道怎么实现了。
折腾了一个晚上加一个上午,终于整出来了。首先是头文件(mylog.h),给出了结构体的定义和一些宏定义:
#ifndef _MYLOG_H_
#define _MYLOG_H_
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/mman.h>
#include <semaphore.h>
#define N_MSG 64 // message的个数
#define LEN_MSG 256 // 每个message的长度
#define FILE_MODE S_IRUSR | S_IWUSR //rwxrwxrwx
#define px_ipc_name(x) (x) //空的宏定义,暂时没有用
struct msg_ctl_str
{
sem_t mutex;
sem_t empty;
sem_t full;
int nput; // 下一个可以由生产者放置log信息的index序号
int nread; // 已经处理完毕的消息序号,初始为-1,这样,下一个要处理的就是0
char msgdata[N_MSG][LEN_MSG];
} msg_ctl_str;
void my_syslog(const char *msg, const char *name); //给客户端的函数
#endif
然后是服务器端的实现:log_server.c
#include "mylog.h"
int main (int argc, char *argv[])
{
struct msg_ctl_str *pmc;
int fd;
int i;
char arg[256];
//缺省参数
if(argc<2)
strncpy(arg,"tmp_name",100);
else
strncpy(arg, argv[1],100);
//防止重名,先删除这个名字的共享内存对象
shm_unlink(arg);
fd = shm_open(arg, O_RDWR|O_CREAT|O_EXCL,S_IRUSR | S_IWUSR);
if(fd==-1)
{
printf("open failed!\n");
exit(2);
}
//内存映射
pmc =
mmap (NULL, sizeof (struct msg_ctl_str), PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0);
ftruncate(fd,sizeof(struct msg_ctl_str));
if (pmc == MAP_FAILED)
{
printf ("map failed!\n");
exit (3);
}
//初始化
sem_init (&(pmc->mutex), 1, 1); //信号量初始化为1,用于互斥访问
sem_init (&(pmc->empty), 1, N_MSG); //信号量初始化为N_MSG,表示有N_MSG个空槽可用
sem_init (&(pmc->full), 1, 0); //信号量初始化为0,表示初始时没有消息要处理
pmc->nput=0; //下一个可以放消息的位置序号从0开始
pmc->nread=-1; // 已经处理完毕的消息index
for (i=0; i<N_MSG;i++) //初始化数据区
{
pmc->msgdata[i][0]='\0';
}
// 循环处理
while (1)
{
sem_wait(&(pmc->full)); //等待有消息的到来,没有消息的话一直阻塞在这里
sem_wait(&(pmc->mutex)); //取得互斥
// 处理!就是打印到标准输出而已