linux多线程 & IPC【12】System V 共享内存
2013-05-13 22:13
302 查看
System V的IPC包括System V消息队列,System V信号量和System共享内存。特征是使用key_t来标志,一般是一个32位的整数,正式说法是一个不小于32位的整数。
没有亲缘关系的进程之间需要约定好一个文件或目录名(反正目录也是文件),以及一个整数值,然后调用ftok()函数返回一个key_t。
key_t类型在<sys/types.h>中定义。
函数ftok原型为:
得到key_t类型的IPC键后,就可以调用shmget函数获得共享内存标志符了。这个标志符是一个int,一般进程间通信,总有一个是相当于服务器的,他来创建这个共享内存,其他进程默认假定该共享内存已经存在。
POSIX 共享内存的大小可以用ftruncate随时修改,但System V的共享内存在shmget调用之后就确定了无法修改。
http://blog.csdn.net/zhangzhenghe/article/details/6838019
1.创建
(1)在服务器端,需要进行创建:
key_t kt = ftok("/home/administrator", 0);
int id = shmget(kt, 1024, IPC_CREAT | 0666);
关键的地方:1024为字节数,IPC_CREAT表示不存在则创建,存在则直接用;IPC_CREAT|IPC_EXCL表示不存在则创建,存在则返回-1退出;0666表示权限,注意前面的0,表示八进制,切记!
(2)在客户端,需要创建:
key_t kt = ftok("/home/administrator", 0);
int id = shmget(kt, 0,0666);
由于共享内存区已经存在,所以第二个参数必须为0,第三个参数也跟creat不相干,指定权限位即可。
int id = shmget(kt, 0,0666);
p = shmat( id, NULL ,0);
p是一个指针,什么指针都行。
然后就可以进行读写了。
int id = shmget(kt, 0,0666);
char *p=shmat(id,NULL,0);
shmdt(p);
int id = shmget(kt, 0,0666);
shmctl(id,IPC_RMID,NULL);
int id = shmget(kt, 0,0666);
struct shmid_ds buff;
shmctl(id,IPC_STAT,&buff);
printf("ize: %d\n", buff.shm_segsz);
System V 共享内存实现之前的系统日志:
包括4个文件:
mylog.h sys_v_cle.c sys_v_ser.c mylog.c
头文件:
sys_v_ser.c。服务器采用独占方式,如果已经存在,则将ftok的第二个参数+1,再次尝试。
sys_v_cle.c:
开启两个终端,第一个终端启动服务器:
第二个终端启动客户端:
没有亲缘关系的进程之间需要约定好一个文件或目录名(反正目录也是文件),以及一个整数值,然后调用ftok()函数返回一个key_t。
key_t类型在<sys/types.h>中定义。
函数ftok原型为:
#include <sys/ipc.h> /* Generates key for System V style IPC. */ key_t ftok (const char *pathname, int proj_id);
得到key_t类型的IPC键后,就可以调用shmget函数获得共享内存标志符了。这个标志符是一个int,一般进程间通信,总有一个是相当于服务器的,他来创建这个共享内存,其他进程默认假定该共享内存已经存在。
POSIX 共享内存的大小可以用ftruncate随时修改,但System V的共享内存在shmget调用之后就确定了无法修改。
http://blog.csdn.net/zhangzhenghe/article/details/6838019
1.创建
(1)在服务器端,需要进行创建:key_t kt = ftok("/home/administrator", 0);
int id = shmget(kt, 1024, IPC_CREAT | 0666);
关键的地方:1024为字节数,IPC_CREAT表示不存在则创建,存在则直接用;IPC_CREAT|IPC_EXCL表示不存在则创建,存在则返回-1退出;0666表示权限,注意前面的0,表示八进制,切记!
(2)在客户端,需要创建:
key_t kt = ftok("/home/administrator", 0);
int id = shmget(kt, 0,0666);
由于共享内存区已经存在,所以第二个参数必须为0,第三个参数也跟creat不相干,指定权限位即可。
2.绑定
key_t kt = ftok("/home/administrator", 0);int id = shmget(kt, 0,0666);
p = shmat( id, NULL ,0);
p是一个指针,什么指针都行。
然后就可以进行读写了。
3.解除绑定
key_t kt = ftok("/home/administrator", 0);int id = shmget(kt, 0,0666);
char *p=shmat(id,NULL,0);
shmdt(p);
4.删除
key_t kt = ftok("/home/administrator", 0);int id = shmget(kt, 0,0666);
shmctl(id,IPC_RMID,NULL);
5.获得大小
key_t kt = ftok("/home/administrator", 0);int id = shmget(kt, 0,0666);
struct shmid_ds buff;
shmctl(id,IPC_STAT,&buff);
printf("ize: %d\n", buff.shm_segsz);
System V 共享内存实现之前的系统日志:
包括4个文件:
mylog.h sys_v_cle.c sys_v_ser.c mylog.c
头文件:
#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> #include <sys/stat.h> #include <sys/shm.h> #define N_MSG 4 // message的个数 #define LEN_MSG 256 // 每个message的长度 //#define FILE_MODE S_IRUSR | S_IWUSR //rwxrwxrwx #define FILE_MODE 00600 //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, char *argv[]); //给客户端的函数 #endif
sys_v_ser.c。服务器采用独占方式,如果已经存在,则将ftok的第二个参数+1,再次尝试。
#include "mylog.h" int main(int argc, char *argv[]) { key_t kt; int id; int n=0; struct msg_ctl_str *p; int i; // 创建共享内存区 kt = ftok(argv[1], atoi(argv[2])+n ); id = shmget(kt, sizeof(struct msg_ctl_str), IPC_CREAT | IPC_EXCL|0666); while (id == -1) { ++n; kt =ftok(argv[1], atoi(argv[2])+n ); id = shmget(kt, sizeof(struct msg_ctl_str), IPC_CREAT | IPC_EXCL|0666); } printf("server start! key_t: %s, %d\n", argv[1], atoi(argv[2])+n ); // 映射 p = shmat( id, NULL ,0); if (p==-1) { printf("shmat fail!\n"); exit(2); } // 初始化 sem_init(&(p->mutex),1,1); sem_init(&(p->empty),1,N_MSG); sem_init(&(p->full),1,0); p->nput=0; p->nread=-1; for(i=0;i<N_MSG;i++) p->msgdata[i][0]='\0'; while(1) { sem_wait(& (p->full)); sem_wait(& (p->mutex)); p->nread++; p->nread %= N_MSG; printf("处理第 %d 条: %s\n", p->nread, p->msgdata[p->nread]); sem_post(& (p->mutex)); sem_post(& (p->empty)); } // 不会运行 shmdt(p); // 断开 shmctl(id, IPC_RMID, NULL); // }
sys_v_cle.c:
#include "mylog.h" int main(int argc, char *argv[]) { char *s="I am client"; my_syslog(s, argv); return 0; }sys_v_cle.c调用了mylog.c中的函数。mylog.c:
#include "mylog.h" void my_syslog (const char *msg, char *argv[]) { key_t kt; int n=0; int id; struct msg_ctl_str *p; // printf("%s %s\n", argv[1], argv[2]); //打开 kt = ftok( argv[1], atoi(argv[2]+n) ); id = shmget(kt,0,0666); while (id == -1) { ++n; kt = ftok( argv[1], atoi(argv[2]+n) ); id=shmget(kt,0,0666); } printf("client key_t: %s, %d--", argv[1], atoi(argv[2])+n ); //映射 p = (struct msg_ctl_str *)shmat(id,NULL,0); if (p==-1) { printf("shmat fail!\n"); exit(2); } //干正事 sem_wait (&(p->empty)); //等待有消息的到来,没有消息的话一直阻塞在这里 sem_wait (&(p->mutex)); //取得互斥 // 处理!就是打印到标准输出而已 strncpy (p->msgdata[p->nput], msg, 255); printf ("process %d add a msg to log (%d, %s)\n", getpid (), p->nput, p->msgdata[p->nput]); p->msgdata[p->nput][255] = '\0'; p->nput++; p->nput = p->nput % N_MSG; // sem_post (&(p->mutex)); sem_post (&(p->full)); //empty的位置增加了一个 }
开启两个终端,第一个终端启动服务器:
administrator@ubuntu:~/test/sys_v$ ./ss /home/administrator 2 & <--启动 [4] 5936 administrator@ubuntu:~/test/sys_v$ server start! key_t: /home/administrator, 4 <--打出来的信息。客户端的参数应使用4 administrator@ubuntu:~/test/sys_v$ jobs [3]- 运行中 ./log_server & (工作目录:~/test/log_test) [4]+ 运行中 ./ss /home/administrator 2 &
第二个终端启动客户端:
administrator@ubuntu:~/test/sys_v$ ./cc /home/administrator 4 client key_t: /home/administrator, 4--process 5937 add a msg to log (0, I am client) administrator@ubuntu:~/test/sys_v$ ./cc /home/administrator 4 client key_t: /home/administrator, 4--process 5938 add a msg to log (1, I am client) administrator@ubuntu:~/test/sys_v$ ./cc /home/administrator 4 client key_t: /home/administrator, 4--process 5939 add a msg to log (2, I am client) administrator@ubuntu:~/test/sys_v$ ./cc /home/administrator 4 client key_t: /home/administrator, 4--process 5940 add a msg to log (3, I am client) administrator@ubuntu:~/test/sys_v$ ./cc /home/administrator 4 client key_t: /home/administrator, 4--process 5941 add a msg to log (0, I am client) administrator@ubuntu:~/test/sys_v$ ./cc /home/administrator 4 client key_t: /home/administrator, 4--process 5942 add a msg to log (1, I am client) administrator@ubuntu:~/test/sys_v$ ./cc /home/administrator 4 client key_t: /home/administrator, 4--process 5943 add a msg to log (2, I am client) administrator@ubuntu:~/test/sys_v$客户端一共运行了7次,写了7条消息。第一个终端中的服务器收到消息,就进行处理,把消息相关的信息打出来:
administrator@ubuntu:~/test/sys_v$ 处理第 0 条: I am client 处理第 1 条: I am client 处理第 2 条: I am client 处理第 3 条: I am client 处理第 0 条: I am client 处理第 1 条: I am client 处理第 2 条: I am client共7条。此后服务器再次进行等待。
相关文章推荐
- linux基础编程:进程通信之System V IPC:消息队列,信号量,共享内存
- System V IPC 之共享内存
- IPC(SystemV) 之 共享内存
- linux system V IPC 信号灯和共享内存实例
- [linux系统编程]System V IPC 共享内存
- Linux进程间通信(IPC)编程实践(七)共享内存的使用-System V共享内存(API)
- linux基础编程:进程通信之System V IPC:消息队列,信号量,共享内存
- System V IPC-信号量,共享内存,消息队列
- linux IPC 通信 study 五:system v 共享内存
- Linux C编程--进程间通信(IPC)5--System V IPC 机制3--共享内存
- 进程间通信总结 && IPC主题三之 共享内存
- Linux C编程--进程间通信(IPC)5--System V IPC 机制3--共享内存
- Linux C编程--进程间通信(IPC)5--System V IPC 机制3--共享内存
- Linux IPC之POSIX共享内存
- System V进程间通信--共享内存
- IPC--共享内存
- IPC 共享内存
- Linux 进程间通讯(IPC)详细总结 5共享内存。
- IPC之共享内存(2)
- 进程-IPC 共享内存和消息队列 (三)