linux下c语言编程4使用共享内存实现进程间通信.docx
《linux下c语言编程4使用共享内存实现进程间通信.docx》由会员分享,可在线阅读,更多相关《linux下c语言编程4使用共享内存实现进程间通信.docx(14页珍藏版)》请在冰豆网上搜索。
linux下c语言编程4使用共享内存实现进程间通信
linux下C语言编程4-使用共享内存实现进程间通信
共享内存的函数有以下几个:
(1)intshmget(key_tkey,intsize,intshmflg),开辟或使用一块共享内存。
(2)void*shmat(intshmid,constvoid*shmaddr,intshmflg),将参数shmid所指向的共享内存与当前进程连接。
当使用某共享内存时,需要先使用shmat,达成连接。
(3)intshmdt(constvoid*shmaddr),将先前用shmat连接的共享内存与当前进程解除连接。
参数shmaddr为shmat返回的共享内存的地址。
在完成对共享内存的使用后,需要使用shmdt解除连接。
(4)intshmctl(intshmid,intcmd,structshmid_ds*buf),控制内存的操作。
当cmd为IPC_RMID时,删除shmid所指的共享内存。
这些函数的表头文件为和,其详细参数请去网上搜索。
下面给出一个使用共享内存实现进程间通信的例子:
进程A开辟一块新的共享内存,进程B修改这个共享内存,进程C打印输出这个共享内存的内容,进程D删除这个共享内存。
进程BCD运行的命令格式为:
命令共享内存ID,如./output123432。
进程A代码如下:
intmain()
{
intshmid;
shmid=shmget(IPC_PRIVATE,SIZE,IPC_CREAT|0600);
if(shmid<0)
{
perror("shmgeterror");
exit
(1);
}
printf("createsharedmemoryOK.shmid=%d/n",shmid);
return0;
}
进程B代码如下:
intmain(intargc,char*argv[])
{
intshmid;
char*shmaddr;
if(argc!
=2)
{
perror("argcerror/n");
exit
(1);
}
shmid=atoi(argv[1]);
shmaddr=(char*)shmat(shmid,NULL,0);
if((int)shmaddr==-1)
{
perror("shmaterror./n");
exit
(1);
}
strcpy(shmaddr,"hello,world!
");
shmdt(shmaddr);
return0;
}
进程C代码如下:
intmain(intargc,char*argv[])
{
intshmid;
char*shmaddr;
if(argc!
=2)
{
printf("argcerror/n");
exit
(1);
}
shmid=atoi(argv[1]);
shmaddr=(char*)shmat(shmid,NULL,0);
if((int)shmaddr==-1)
{
perror("shmaterror./n");
exit
(1);
}
printf("%s/n",shmaddr);
shmdt(shmaddr);
return0;
}
进程D代码如下:
intmain(intargc,char*argv[])
{
intshmid;
if(argc!
=2)
{
perror("argcerror/n");
exit
(1);
}
shmid=atoi(argv[1]);
shmctl(shmid,IPC_RMID,NULL);
return0;
}
linux下C语言编程5-多线程编程
Linux系统下的多线程遵循POSIX线程接口,称为pthread。
编写Linux下的多线程程序,需要使用头文件pthread.h,编译需要在后面加-lpthread。
关于多线程,主要有以下几个过程:
1,创建线程
2,各个线程的执行
3,等待线程的结束
涉及的线程函数主要有:
1,intpthread_create(pthread_t*restricttidp,constpthread_attr_t*restrictattr,void*(*start_rtn)(void), void*restrictarg);
函数有4个参数:
第一个参数为指向线程标识符的指针。
第二个参数用来设置线程属性。
第三个参数是一个函数指针(有关函数指针,看这里),指向线程运行函数的起始地址。
最后一个参数是函数指针所需要的参数。
注意:
pthread_create函数返回0表示成功。
另外如果函数指针需要多个参数的话,就将这些参数做成某个结构体,作为第4个参数。
如果有返回值的话,也可将返回值的指针回写到第4个参数中。
2,pthread_join()等待一个线程的结束。
pthread_exit()用于线程退出,可以指定返回值,以便其他线程通过pthread_join()函数获取该线程的返回值。
线程的应用:
并行数据库的查询
假设我们有3台计算机A,B,C,每台均安装PG数据库,通过网络连接。
我们可以通过多线程将查询SQL广播出去,A,B,C并行查询,最终返回各自的结果。
如果没有多线程,而只是用了个循环,那么我们获取结果的过程将是顺序的,即等A的结果返回后才能查询B,B结束后查询C,效率低下。
代码如下:
//最多支持MAX个线程#defineMAX16
/****多线程******/
typedefstructPDthread
{
char*host;//IP
intport;//端口
char*dbname;//数据库名
char*query;//SQL语句
void*rst;//查询结果
}PDthread;
typedefstructNodes
{
intcount;//实际上的节点数量count<=MAX
charhost[MAX][32];
intport[MAX];
}Nodes;/*线程的执行过程,参数m为PDthread结构*/
void*PDthreadSelect(void*m)
{
PDthread*p=(PDthread*)m;
p->rst=(void*)ExecuteQuery(p->host,p->port,p->dbname,p->query);
pthread_exit(NULL);
returnNULL;
}/*创建多个线程,1个node对应1个线程*输出:
thread[],pdthread*输入:
node,dbname,query,这些值写到pdthread变量中,传递给函数PDthreadSelect(因为此函数只能有一个参数)*/
voidPDthreadCreate(pthread_tthread[],PDthread*pdthread,Nodes*node,char*dbname,char*query)
{
inttmp;
inti;
PDthread*p;
for(i=0;icount;i++)
{
//把Nodes作为PDthread的一部分
p=pdthread+i;
p->host=node->host[i];
p->port=node->port[i];
p->dbname=dbname;
p->query=query;
tmp=pthread_create(&thread[i],NULL,PDthreadSelect,p);
if(tmp!
=0)printf("PDthreadCreate:
线程%d创建失败!
/n",i);
elseprintf("PDthreadCreate:
线程%d被创建/n",i);
}
}
voidPDthreadWait(pthread_tthread[],intcount)
{
//等待线程结束
inti;
for(i=0;i{
if(thread[i]!
=0)
{
pthread_join(thread[i],NULL);
printf("线程%d已经结束/n",i);
}
}
}
intmain()
{
Nodesnode;node.count=3;
strcpy(node.host[0],"192.168.0.1");
node.port[0]=5432;
strcpy(node.host[1],"192.168.0.2");
node.port[1]=5432;
strcpy(node.host[2],"192.168.0.3");
node.port[2]=5432;//使用多线程去获取数据
pthread_tthread[MAX];
memset(&thread,0,sizeof(thread));//获取结果
PDthread*pdthread=(PDthread*)malloc(node.count*sizeof(PDthread));
PDthreadCreate(thread,pdthread,&node,"database","SELECT*FROMstudent");
PDthreadWait(thread,node.count);//返回结果存储在pdthread->rst
return0;
}
编译命令:
gcc-I/usr/local/pgsql/include-othth.c-L/usr/local/pgsql/lib-lpq-lpthread,因为使用了libpq库。
Linux下通过共享内存进行进程间通信,进程间同步使用信号量来实现(Linux环境下C编程指南)
Linux环境下C编程指南,通过共享内存进行进程间通信的例子,进程间同步使用信号量来实现。
使用说明:
这是一个简单的服务器和客户端程序,如果启动程序时不带参数,则执行服务器程序;
如果带参数,则执行客户端程序,所带参数只有一个,就是服务器端所显示的共享内存的引用ID。
实现原理:
服务器端启动后,创建信号量和共享内存,并将共享内存的引用ID显示出来,将信号量
的引用ID存放在共享内存中。
客户端启动后,利用服务器端提供的内存共享ID将共享内存附加到地址段,读取信号量以实现两个进程之间的同步。
之后,这两个进程就可以利用共享内存进行进程间通信,客户端输入的信息将在服务器端显示出来。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#defineSHMDATASIZE1000
#defineBUFFERSIZE(SHMDATASIZE-sizeof(int))
#defineSN_EMPTY0
#defineSN_FULL1
intdeleteSemid=0;
unionsemun
{
intval;
structsemid_ds*buf;
unsignedshortint*array;
structseminfo*__buf;
};
voidserver(void);//不加参数时执行
voidclient(intshmid);
voiddelete(void);
voidsigdelete(intsignum);
voidlocksem(intsemid,intsemnum);
voidunlocksem(intsemid,intsemnum);
voidwaitzero(intsemid,intsemnum);
voidclientwrite(intshmid,intsemid,char*buffer);
intsafesemget(key_tkey,intnsems,intsemflg);
intsafesemctl(intsemid,intsemnum,intcmd,unionsemunarg);
intsafesemop(intsemid,structsembuf*sops,unsignednsops);
intsafeshmget(key_tkey,intsize,intshmflg);
void*safeshmat(intshmid,constvoid*shmaddr,intshmflg);
intsafeshmctl(intshmid,intcmd,structshmid_ds*buf);
intmain(intargc,char*argv[])
{
if(argc<2)
{
server();
}
else
{
client(atoi(argv[1]));
}
return0;
}
voidserver(void)
{
unionsemunsunion;
intsemid,shmid;
void*shmdata;
char*buffer;
semid=safesemget(IPC_PRIVATE,2,SHM_R|SHM_W);
deleteSemid=semid;
atexit(&delete); //当程序终止执行时,执行delete函数
signal(SIGINT,&sigdelete);//接收到信号SIGINT则执行sigdelete函数
sunion.val=1;
safesemctl(semid,SN_EMPTY,SETVAL,sunion);
sunion.val=0;
safesemctl(semid,SN_FULL,SETVAL,sunion);
shmid=safeshmget(IPC_PRIVATE,SHMDATASIZE,IPC_CREAT|SHM_R|SHM_W);
shmdata=safeshmat(shmid,0,0);
safeshmctl(shmid,IPC_RMID,NULL);//删除共享内存,当所有附加该共享内存的进程结束或断开与该共享内存的连接时才执行
*(int*)shmdata=semid;
buffer=shmdata+sizeof(int);
printf("ServerisrunningwithSHMid**%d**\n",shmid);
while
(1)
{
printf("Waitinguntilfull...");
fflush(stdout);
locksem(semid,SN_FULL);
printf("done.\n");
printf("Messagereceived:
%s.\n",buffer);
unlocksem(semid,SN_EMPTY);
}
}
voidclient(intshmid)
{
intsemid;
void*shmdata;
char*buffer;
shmdata=safeshmat(shmid,0,0);
semid=*(int*)shmdata;
buffer=shmdata+sizeof(int);
printf("Clientoperational:
shmidis%d,semidis%d\n",shmid,semid);
while
(1)
{
charinput[3];
printf("\n\nMenu\n1.sendamessage\n");
printf("2.Exit\n");
fgets(input,sizeof(input),stdin);
switch(input[0])
{
case'1':
clientwrite(shmid,semid,buffer);
break;
case'2':
exit(0);
break;
}
}
}
voiddelete(void)
{
printf("\nMasterexiting;deletingsemaphore%d.\n",deleteSemid);
if(semctl(deleteSemid,0,IPC_RMID,0)==-1)
{
printf("Errorreleasingsemaphore.\n");
}
}
voidsigdelete(intsignum)
{
exit(0);
}
voidlocksem(intsemid,intsemnum)
{
structsembufsb;
sb.sem_num=semnum;
sb.sem_op=-1;
sb.sem_flg=SEM_UNDO;
safesemop(semid,&sb,1);
}
voidunlocksem(intsemid,intsemnum)
{
structsembufsb;
sb.sem_num=semnum;
sb.sem_op=1;
sb.sem_flg=SEM_UNDO;
safesemop(semid,&sb,1);
}
voidwaitzero(intsemid,intsemnum)
{
structsembufsb;
sb.sem_num=semnum;
sb.sem_op=0;
sb.sem_flg=0;
safesemop(semid,&sb,1);
}
voidclientwrite(intshmid,intsemid,char*buffer)
{
printf("Waitinguntilempty...");
fflush(stdout);
locksem(semid,SN_EMPTY);
printf("done.\n");
printf("EnterMessage:
");
fgets(buffer,BUFFERSIZE,stdin);
unlocksem(semid,SN_FULL);
}
intsafesemget(key_tkey,intnsems,intsemflg)
{
intretval;
if((retval=semget(key,nsems,semflg))==-1)
{
printf("semgeterror:
%s.\n",strerror(errno));
exit(254);
}
returnretval;
}
intsafesemctl(intsemid,intsemnum,intcmd,unionsemunarg)
{
intretval;
if((retval=semctl(semid,semnum,cmd,arg))==-1)
{
printf("semctlerror:
%s.\n",strerror(errno));
exit(254);
}
returnretval;
}
intsafesemop(intsemid,structsembuf*sops,unsignednsops)
{
intretval;
if((retval=semop(semid,sops,nsops))==-1)
{
printf("semoperror:
%s.\n",strerror(errno));
exit(254);
}
returnretval;
}
intsafeshmget(key_tkey,intsize,intshmflg)
{
intretval;
if((retval=shmget(key,size,shmflg))==-1)
{
printf("shmgeterror:
%s.\n",strerror(errno));
exit(254);
}
returnretval;
}
void*safes