unix_c++学习笔记4
内容:
* 高级进程通信技术 -- IPC

1. 3中常用IPC技术:
* Message queue
* Semaphore
* Share Memory

2. 有关的系统命令
* ipcs
查看已经建立的IPC资源
* ipcrm
删除IPC资源

3. ftok函数
* 资源的ID由KEY产生,ftok用于生成不重复的KEY
#include<sys/ipc.h>
key_t ftok( const char* path, int id );
path是一个已经存在的文件名,id是一个数字
只要每次使用的path或id有一个不同就回产生不同的KEY
KEY值也可自己指定

4. Semaphore信号量
* 用于对临界资源进行控制
* 程序中建立semaphore表,一个表有一个semid, 表中登记临界资源及其数量
* semaphore的常见操作:
(1)建表,指定资源个数
(2)初始化
(3)查看,具体或全部
(4)修改
* int semget( key_t key, int nsems, int flag )
建立新表或获取表
semget( key, nsems, IPC_CREAT | 0777 ) 建立新表,nsems指定资源数
int id = semget( key, 0, 0 ) 获取表
例子:

#include<iostream>
#include<sys/ipc.h>
#include<sys/sem.h>
#include<error.h>
using namespace std;

const int key = 0x2345;
int main(){
int nsems=0;
cout<<"enter nsems > ";
cin>>nsems;
int id = semget( key, nsems, IPC_CREAT | 0666 );
// create a semaphore
if( id < 0 ){
cout<< strerror( errno ) <<endl;
exit( -1 );
}else{
cout<<
"create semaphore successful, id = "<< id <<endl;
}
return 0;
}



* int semctl( int semid, int semnum, int cmd, union semun arg )
semnum指定表中的具体资源
cmd 指定操作方式:
(1)IPC_STAT 得到资源表的状态
(2)IPC_RMID 删除一个资源表
(3)GETVAL 取某一个值
(4)SETVAL 设定某一个的值
(5)GETALL 取全部值
(6)SETALL 设全部值
union semun{
int val; // for SETVAL
struct semid_ds *buf; // for IPC_STAT, 描述一个表的属性,其中最常用的是 ushort sem_nsems,可以得到资源个数
shor* array; // for GETALL and SETALL
};

例子:

#include<iostream>
#include<sys/ipc.h>
#include<sys/sem.h>
using namespace std;

const int key = 0x2345;
union semun{
int val;
struct semid_ds * buf;
short * array;
};
int main(){
int id = semget( key, 0, 0 );
// get semaphore id by key
if( id < 0 ){
cout<<
"can not get semaphore by "<< key <<endl;
exit( -1 );
}else{
cout<<
"get semaphore, id = "<< id <<endl;
}

// get number of semaphore in the set
struct semid_ds ds;
union semun arg;
arg.buf = &ds;
semctl( id, 0, IPC_STAT, arg );
cout<<
"number of semaphore in "<< id << " is "<< ds.sem_nsems <<endl;

// assign a value
int nsems=ds.sem_nsems;
for( int i=0; i<nsems; i++ ){
cout<<
"enter value for semaphore "<< i <<" > "<<endl;
cin>>arg.val;
semctl( id, i, SETVAL, arg );
}
cout<<
"------------ getval -----------"<<endl;
int value;
for( int i=0;i<nsems;i++ ){
value= semctl( id, i, GETVAL, NULL );
cout<<i<<
" "<<value<<endl;
}

cout<<
"------------ getAll ------------"<<endl;
short all[ nsems ];
arg.array = all;
semctl( id, 0, GETALL, arg );
for( int i=0;i<nsems;i++ ){
cout<<
"all[ "<< i <<" ]="<< all<i> <<endl;
}
return 0;
}



* int semop( int semid, struct sembuf semoparray[], size_t nops ) 对表进行操作
struct sembuf{
ushort sem_num; // number of semaphore in set
short sem_op; // operator, -n or +n
short sem_flag; // IPC_NOWAIT
};
nops 说明共操作几项

例子:

#include<iostream>
#include<sys/sem.h>
#include<sys/ipc.h>
using namespace std;

const int key=0x2345;
union semun{
int val;
struct semid_ds * buf;
short * array;
};
void show_sem( int id ){
short all[3];
union semun arg;
arg.array = all;
semctl( id, 0, GETALL, arg );
for( int i=0; i<3; i++ ){
cout<<
"value "<< i << "=" << all<i> <<endl;
}
}
int main(){
int id = semget( key, 0, 0 );
struct sembuf ops[ 3 ];
for( int i=0; i<3; i++ ){
cout<<
"enter operation for sem "<< i <<" > ";
ops<i>.sem_num=i;
cin>>ops<i>.sem_op;
}
cout<<
"------------ befor semop ------------"<<endl;
show_sem( id );
semop( id, ops, 3 );
cout<<
"------------ after semop -------------"<<endl;
show_sem( id );

return 0;
}



* 删除
例子:

#include<iostream>
#include<sys/ipc.h>
#include<sys/sem.h>
using namespace std;

const int key=0x2345;
int main(){
int id=semget( key, 0, 0 );
semctl( id, 0, IPC_RMID, NULL );
cout<<
"semaphore removed ..."<<endl;
return 0;
}



5. Message Queue 信息队列
* 信息的链表,由内核维护
* 创建一个信息队列
msqid = msgget( key, IPC_CREAT|0666 );
* struct mymsg{
long mtype;
char mtest[MAX_MSG_LENGTH];
};
* int msgsnd( int msqid, const void * ptr, size_t msgsz, int flag );
ptr为msg结构的地址
msgsz = length of msg
flag = 0
* int msgrcv( int msqid, void * ptr, size_t nbytes, long type, int flag );
ptr=msgbuf 结构
nbytes=最大消息长度
type=消息类型
(1)0按顺序取第一条记录
(2)>0 取队列中类型为type的第一条消息
* 谁创建 谁删除
例子:

// 头文件
#ifndef __MSG_SAMPLE_H__
#define __MSG_SAMPLE_H__
const int MSG_SIZE=100;
const int key=0x1234;
struct mymsg{
long type;
char msg[ MSG_SIZE ];
};
#endif



// 创建队列,发送消息,等待接收信号删除队列

#include<iostream>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<signal.h>
#include<sys/types.h>
#include<unistd.h>
#include
"msg_test.h"
using namespace std;

void handler( int sig );
int main(){
if( signal( SIGUSR1, handler )==SIG_ERR ){
cout<<
"signal error"<<endl;
exit( -1 );
}
// create message queue
int id = msgget( key, IPC_CREAT|0666 );
if( id < 0 ){
cout<<
"create message queue error"<<endl;
exit( -1 );
}else{
cout<<
"create message queue successful, id = "<< id <<endl;
}

struct mymsg m;
memset( &m, 0x00, sizeof( m ) );
m.type=1;
cout<<
"enter a line for sending > ";
cin.getline( m.msg, sizeof( m.msg ) );

// send msg
msgsnd( id, &m, sizeof( m ), 0 );
cout<<
"send message ok..."<<endl;
cout<<
"process id = "<<getpid()<< endl;
pause();
// wait receive confirm signal

return 0;
}

void handler( int sig ){
cout<<
"capture signal "<< sig <<endl;
int id = msgget( key,0 );
msgctl( id, IPC_RMID, NULL );
cout<<
"remove message queue ok..."<<endl;
}



// 接收消息,发出信号

#include<iostream>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<signal.h>
#include<sys/types.h>
#include<unistd.h>
#include
"msg_test.h"
using namespace std;

int main(){
struct mymsg m;
memset( &m, 0x00, sizeof( m ) );

int id = msgget( key, 0 );
if( id < 0 ){
cout<<
"get message queue error. "<<endl;
exit( -1);
}else{
cout<<
"get message queue successful, id = "<< id <<endl;
}

msgrcv( id, &m, sizeof( m ), 0, 0 );
cout<<
"get message [ "<< m.msg <<" ]"<<endl;

pid_t pid;
cout<<
"enter pid > ";
cin>>pid;
kill( pid, SIGUSR1 );
// send confirm signal
return 0;
}



6. Share Memory 共享存储
* 在系统中建一片公共场所,不同进程可以共享该区域
数据不需要复制,速度很快,需要同步机制开控制存储
就是一些文件操作
* #include<sys/types.h>
#include<sys/ipc.h>
#include<sys/shm.h>
int shmget( key_t key, int size, int flag );
int shmctl( int shmid, int cmd, struct shid_ds * buf );
void *shmat( int shmid, vodi *addr, int flag );
int shmdt( void* addr );

例子:

// 头文件
#ifndef __SHM_TEST__
#define __SHM_TEST__
const int SHM_SIZE = 27;
const int key=0x1234;

#endif



// 建立共享内存,初始化为 a--z, 直到第一个字母被改为‘*’结束

#include<iostream>
#include<sys/ipc.h>
#include<sys/types.h>
#include<unistd.h>
#include<sys/shm.h>
#include
"shm_test.h"

using namespace std;

int main(){
char * p;
char * temp;
p = temp= NULL;

int id= shmget( key, SHM_SIZE, IPC_CREAT | 0666 );
if( id< 0 ){
cout<<
"error"<<endl;
exit( -1 );
}

p = (char*)shmat( id, NULL, 0 );
temp = p;
// init shm a--z
char c;
for( c='a'; c<='z'; c++ ){
*temp++ = c;
}
*temp = '\0';

while( *p != '*' ){
sleep( 1 );
}

return 0;
}



// 取得共享内存信息,将首字母改为‘*’

#include<iostream>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<unistd.h>
#include
"shm_test.h"
using namespace std;

int main(){
int id = shmget( key, 0, 0 );

char* p=NULL;
p = (char*)shmat( id, NULL, 0 );
cout<<
"[ "<<p<<" ]"<<endl;

*p='*';
shmdt( p );
return 0;
}




irini   2005-10-17 21:48:19 评论:0   阅读:831   引用:0

发表评论>>

署名发表(评论可管理,不必输入下面的姓名)

姓名:

主题:

内容: 最少15个,最长1000个字符

验证码: (如不清楚,请刷新)

Copyright@2008 powered by YuLog