📄 计算机世界网-unix中多程序间共享内存.htm
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- saved from url=(0048)http://www.ccw.com.cn/htm/app/aprog/01_1_4_2.asp -->
<HTML><HEAD><TITLE>计算机世界网-Unix中多程序间共享内存</TITLE>
<META content="text/html; charset=gb2312" http-equiv=Content-Type>
<STYLE>.a14 {
FONT-SIZE: 14px; LINE-HEIGHT: 20px; TEXT-INDENT: 25px
}
.f {
COLOR: #0f3ccd; FONT-SIZE: 18px
}
IMG {
BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; BORDER-RIGHT: 0px; BORDER-TOP: 0px
}
TD {
FONT-SIZE: 12px; font-fammily: verdana,宋体
}
P {
FONT-SIZE: 12px; font-fammily: verdana,宋体
}
INPUT {
FONT-SIZE: 12px; font-fammily: verdana,宋体
}
A:link {
COLOR: black; TEXT-DECORATION: none
}
A:visited {
COLOR: #80006f; TEXT-DECORATION: none
}
A:hover {
COLOR: black; TEXT-DECORATION: underline
}
</STYLE>
<META content="MSHTML 5.00.3700.6699" name=GENERATOR></HEAD>
<BODY leftMargin=0 topMargin=2>
<CENTER>
<STYLE>.v12 {
COLOR: #ffffff; FONT-SIZE: 10pt; FONT-WEIGHT: bold
}
.v14 {
FONT-SIZE: 14px; LINE-HEIGHT: 20px; TEXT-INDENT: 25px
}
IMG {
BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; BORDER-RIGHT: 0px; BORDER-TOP: 0px
}
TD {
FONT-SIZE: 12px; font-fammily: verdana,宋体
}
P {
FONT-SIZE: 12px; font-fammily: verdana,宋体
}
INPUT {
FONT-SIZE: 12px; font-fammily: verdana,宋体
}
SELECT {
FONT-SIZE: 12px; font-fammily: verdana,宋体
}
A:link {
COLOR: black; TEXT-DECORATION: none
}
A:visited {
COLOR: #80006f; TEXT-DECORATION: none
}
A:hover {
COLOR: black; TEXT-DECORATION: underline
}
</STYLE>
<STYLE>.v13 {
COLOR: #ffffff; FONT-SIZE: 10pt; FONT-WEIGHT: bold
}
.v12 {
COLOR: #4c029c; FONT-SIZE: 13px; FONT-WEIGHT: bold
}
.v14 {
FONT-SIZE: 14px; LINE-HEIGHT: 20px; TEXT-INDENT: 25px
}
IMG {
BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; BORDER-RIGHT: 0px; BORDER-TOP: 0px
}
TD {
FONT-SIZE: 12px; font-fammily: verdana,宋体
}
P {
FONT-SIZE: 12px; font-fammily: verdana,宋体
}
INPUT {
FONT-SIZE: 12px; font-fammily: verdana,宋体
}
SELECT {
FONT-SIZE: 12px; font-fammily: verdana,宋体
}
A:link {
COLOR: black; TEXT-DECORATION: none
}
A:visited {
COLOR: #80006f; TEXT-DECORATION: none
}
A:hover {
COLOR: black; TEXT-DECORATION: underline
}
</STYLE>
<!--头-->
<TABLE align=center border=0 cellPadding=0 cellSpacing=0 width=767>
<TBODY>
<TR>
<TD vAlign=bottom>
<TABLE border=0 cellPadding=0 cellSpacing=0>
<TBODY>
<TR>
<TD vAlign=top><IMG
src="计算机世界网-Unix中多程序间共享内存.files/ccwlogo.gif"></TD></TR>
<TR>
<TD height=27 vAlign=top><IMG height=27
src="计算机世界网-Unix中多程序间共享内存.files/knowledge.gif"
width=207></TD></TR></TBODY></TABLE></TD>
<TD bgColor=#4c029c height=96 vAlign=bottom width=556>
<TABLE bgColor=#4c029c border=0 cellPadding=0 cellSpacing=0 height=96
width=556>
<TBODY>
<TR>
<TD bgColor=#ffffff colSpan=2 height=25 vAlign=bottom><IMG
src="计算机世界网-Unix中多程序间共享内存.files/top.gif" useMap=#F></TD></TR>
<TR vAlign=center>
<TD align=middle height=60 vAlign=center><!-- <a href="/search/" target=_blank><img src="/img2/esearch.GIF" border=0 width=468 height=60></a> --><A
href="http://www.ccw.com.cn/html/search/thememail/"
target=_blank><IMG border=0 height=60
src="计算机世界网-Unix中多程序间共享内存.files/topbanner_thememail.gif"
width=468></A> </TD>
<TD align=middle width="15%">
<TABLE width="95%">
<TBODY>
<TR>
<TD><A href="mailto:center@ccw.com.cn?subject=我要投稿:"
target=_blank><FONT class=v13>我要投稿</A><BR><A
href="mailto:center@ccw.com.cn?subject=编读往来"><FONT
class=v13>编读往来</A><BR><A
href="javascript:AddBookMark('计算机世界网首页')"><FONT
class=v13>加入收藏</A></FONT></FONT></FONT></TD></TR></TBODY></TABLE></TD></TR>
<TR>
<TD bgColor=#ffffff colSpan=2 height=1></TD></TR>
<TR>
<TD bgColor=#b4aafc colSpan=2 height=2></TD></TR></TBODY></TABLE><MAP
name=F><AREA coords=29,3,61,18 href="http://www.ccw.com.cn/" shape=RECT
target=_blank><AREA coords=72,3,143,18
href="http://www.ccw.com.cn/news1/" shape=RECT target=_blank><AREA
coords=155,2,216,18 href="http://www.ccw.com.cn/center/" shape=RECT
target=_blank><AREA coords=225,2,299,18
href="http://www.ccw.com.cn/work/" shape=RECT target=_blank><AREA
coords=310,3,364,19 href="http://www.ccw.com.cn/search/" shape=RECT
target=_blank><AREA coords=372,2,412,19 href="http://www3.ccw.com.cn/"
shape=RECT target=_blank><AREA coords=424,2,550,18
href="http://www2.ccw.com.cn/" shape=RECT target=_blank></MAP></TD></TR>
<TR>
<TD bgColor=#b4aafc colSpan=2>
<TABLE border=0 cellPadding=0 cellSpacing=0 width="100%">
<TBODY>
<TR>
<TD align=middle width="26%"><FONT
class=v12>【2004年8月19日】 </FONT></TD>
<TD class=V12><A href="http://www.ccw.com.cn/center/topic.asp">专
题</A> /</TD>
<TD class=V12><A href="http://www.ccw.com.cn/center/tech.asp">技
术</A> /</TD>
<TD class=V12><A href="http://www.ccw.com.cn/center/prod.asp">产
品</A> /</TD>
<TD class=V12><A href="http://www.ccw.com.cn/center/app.asp">应
用</A> /</TD>
<TD class=V12><A href="http://www.ccw.com.cn/center/net.asp">网
络</A> /</TD>
<TD class=V12><A href="http://www.ccw.com.cn/center/prog.asp">编
程</A> /</TD>
<TD class=V12><A href="http://www.ccw.com.cn/center/skill.asp">技
巧</A> </TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE>
<TABLE align=center width=680>
<TBODY>
<TR>
<TD align=middle><BR>
<H2><FONT color=#0f3ccd>Unix中多程序间共享内存</FONT></H2><BR><B>北京网擎科技 许杨春</B>
<BR>
<HR color=#f46240 SIZE=1 width=660>
</TD></TR></TBODY></TABLE><BR>
<TABLE align=center width=620>
<TBODY>
<TR>
<TD class=a14>共享内存 (shared memory)是 Unix下的多进程之间的通信方法
,这种方法通常用于一个程序的多进程间通信,实际上多个程序间也可以通过共享内存来传递信息。本文介绍如何在
Client/Server方式下实现多个程序间共享内存。 </TD></TR></TBODY></TABLE>
<TABLE align=center width=620>
<TBODY>
<TR>
<TD class=a14><B>问题分析<B></B></B></TD></TR></TBODY></TABLE>
<TABLE align=center width=620>
<TBODY>
<TR>
<TD class=a14>多个程序之间共享内存 ,首先要解决的问题是怎样让各个程序能够访问同一块内存和相同的信号量。共享内存的 id可以通过调用
shmget(key_t key, size_t size, int shmflg)函数取得;信号量的 id可以通过调用 semget(key_t
key, int nsems, int semflg)函数取得。实际上,只要在调用这两个函数时使用相同的
key值,各程序之间就能达到共享内存的目的。 Unix通过调用 key_t ftok(const char* path, int id)函数来产生
key值 ,如果各程序都用同样的参数来调用此函数,自然也就得到相同的 key值了。例子中各个程序都使用 key=ftok(" /", 0)得到相同的
key值 ,再进而由 key值得到相同的共享内存 id和信号量 id。 </TD></TR></TBODY></TABLE>
<TABLE align=center width=620>
<TBODY>
<TR>
<TD class=a14>第二个要解决的问题是如何控制多个程序并发访问共享内存。本文的例子模拟在 Client/Server方式下,由一个
Server产生数据,多个 Client去读取数据的操作。常规的方法是设一个信号量,将访问共享内存的程序作为临界区来处理。程序进入时用
p()操作取得锁,退出时用 v()操作释放锁。但这样做有两个问题:一是这样各个程序就处于平等的地位,而实际中往往 Server的优先级应该比
Client更高。比如,在股票行情应用程序中 ,共享内存里存放行情信息, Server负责定时更新; Client是
CGI程序,负责按客户要求读取共享内存中的数据,然后再反馈给客户。在这种情况下, Server就不能等所有
Client进程都读完了才开始写,因为这样 Client取得的数据反而是过时的。二是各个 Client之间由于都是读操作,所以没有必要互斥。
</TD></TR></TBODY></TABLE>
<TABLE align=center width=620>
<TBODY>
<TR>
<TD class=a14>本文对这两个问题的解决方案是:只有 Server进行 p()、 v()操作,信号量初始值设为 0, p()操作将它加一,
v()操作将它减一; Client读共享内存之前要先等待信号量的值为 0,这样 Server的 p()操作总是成功,而 Server的
p()操作后,尚未进入临界区的 Client只能等到 Server执行 v()操作后才能读。这样 Server比 Client优先,
Client之间不互斥。但这样又产生另一个问题:一个 Server开始写时,部分
Client可能已经进入临界区,有可能出现读不完整的问题。因此,例子基于这样一个前提:
Client程序比较简单,不会被阻塞,并且能够在一个时间片内执行完读取操作。本例中处于临界区中的 Client数目是有限的,如果
Server等待一个时间片 (例子中是等待一分钟 )后, Client就能全部退出临界区,这个问题就能排除。很多
CGI程序能够满足这个假设条件,如果 Client确实不满足条件,可以生成访问共享内存的子进程,它的执行时间应该满足上述要求。
</TD></TR></TBODY></TABLE>
<TABLE align=center width=620>
<TBODY>
<TR>
<TD class=a14><B>应用实例</B></TD></TR></TBODY></TABLE>
<TABLE align=center width=620>
<TBODY>
<TR>
<TD class=a14>下面给出实现多程序间共享内存的例子程序的部分代码: </TD></TR></TBODY></TABLE>
<TABLE align=center width=620>
<TBODY>
<TR>
<TD class=a14>1.Server端程序 </TD></TR></TBODY></TABLE>
<TABLE align=center width=620>
<TBODY>
<TR>
<TD class=a14># define SEGSIZE 1024 </TD></TR></TBODY></TABLE>
<TABLE align=center width=620>
<TBODY>
<TR>
<TD class=a14># define READTIME 1 </TD></TR></TBODY></TABLE>
<TABLE align=center width=620>
<TBODY>
<TR>
<TD class=a14>union semun { </TD></TR></TBODY></TABLE>
<TABLE align=center width=620>
<TBODY>
<TR>
<TD class=a14>int val; </TD></TR></TBODY></TABLE>
<TABLE align=center width=620>
<TBODY>
<TR>
<TD class=a14>struct semid_ds* buf; </TD></TR></TBODY></TABLE>
<TABLE align=center width=620>
<TBODY>
<TR>
<TD class=a14>ushort_t* array; </TD></TR></TBODY></TABLE>
<TABLE align=center width=620>
<TBODY>
<TR>
<TD class=a14>} ; </TD></TR></TBODY></TABLE>
<TABLE align=center width=620>
<TBODY>
<TR>
<TD class=a14>//生成信号量 </TD></TR></TBODY></TABLE>
<TABLE align=center width=620>
<TBODY>
<TR>
<TD class=a14>int sem(key_t key){ </TD></TR></TBODY></TABLE>
<TABLE align=center width=620>
<TBODY>
<TR>
<TD class=a14>union semun sem ; </TD></TR></TBODY></TABLE>
<TABLE align=center width=620>
<TBODY>
<TR>
<TD class=a14>int semid; </TD></TR></TBODY></TABLE>
<TABLE align=center width=620>
<TBODY>
<TR>
<TD class=a14>sem.val=0; </TD></TR></TBODY></TABLE>
<TABLE align=center width=620>
<TBODY>
<TR>
<TD class=a14>semid=semget(key,1,IPC_CREAT|0666); </TD></TR></TBODY></TABLE>
<TABLE align=center width=620>
<TBODY>
<TR>
<TD class=a14>if (semid ==- 1){ </TD></TR></TBODY></TABLE>
<TABLE align=center width=620>
<TBODY>
<TR>
<TD class=a14>printf(" create semaphore error\n" ); </TD></TR></TBODY></TABLE>
<TABLE align=center width=620>
<TBODY>
<TR>
<TD class=a14>exit(- 1); </TD></TR></TBODY></TABLE>
<TABLE align=center width=620>
<TBODY>
<TR>
<TD class=a14>} </TD></TR></TBODY></TABLE>
<TABLE align=center width=620>
<TBODY>
<TR>
<TD class=a14>//初始化信号量 </TD></TR></TBODY></TABLE>
<TABLE align=center width=620>
<TBODY>
<TR>
<TD class=a14>semctl(semid,0,SETVAL,sem); </TD></TR></TBODY></TABLE>
<TABLE align=center width=620>
<TBODY>
<TR>
<TD class=a14>return semid; </TD></TR></TBODY></TABLE>
<TABLE align=center width=620>
<TBODY>
<TR>
<TD class=a14>} </TD></TR></TBODY></TABLE>
<TABLE align=center width=620>
<TBODY>
<TR>
<TD class=a14>//删除信号量 </TD></TR></TBODY></TABLE>
<TABLE align=center width=620>
<TBODY>
<TR>
<TD class=a14>void d_sem(int semid){ </TD></TR></TBODY></TABLE>
<TABLE align=center width=620>
<TBODY>
<TR>
<TD class=a14>union semun sem ; </TD></TR></TBODY></TABLE>
<TABLE align=center width=620>
<TBODY>
<TR>
<TD class=a14>sem.val=0; </TD></TR></TBODY></TABLE>
<TABLE align=center width=620>
<TBODY>
<TR>
<TD class=a14>semctl(semid,0,IPC_RMID,0); </TD></TR></TBODY></TABLE>
<TABLE align=center width=620>
<TBODY>
<TR>
<TD class=a14>} </TD></TR></TBODY></TABLE>
<TABLE align=center width=620>
<TBODY>
<TR>
<TD class=a14>int p(int semid){ </TD></TR></TBODY></TABLE>
<TABLE align=center width=620>
<TBODY>
<TR>
<TD class=a14>struct sembuf sops={0,+ 1,IPC_NOWAIT}; </TD></TR></TBODY></TABLE>
<TABLE align=center width=620>
<TBODY>
<TR>
<TD class=a14>return(semop(semid,& sops,1)); </TD></TR></TBODY></TABLE>
<TABLE align=center width=620>
<TBODY>
<TR>
<TD class=a14>} </TD></TR></TBODY></TABLE>
<TABLE align=center width=620>
<TBODY>
<TR>
<TD class=a14>int v(int semid){ </TD></TR></TBODY></TABLE>
<TABLE align=center width=620>
<TBODY>
<TR>
<TD class=a14>struct sembuf sops={0,- 1,IPC_NOWAIT}; </TD></TR></TBODY></TABLE>
<TABLE align=center width=620>
<TBODY>
<TR>
<TD class=a14>return(semop(semid,& sops,1)); </TD></TR></TBODY></TABLE>
<TABLE align=center width=620>
<TBODY>
<TR>
<TD class=a14>} </TD></TR></TBODY></TABLE>
<TABLE align=center width=620>
<TBODY>
<TR>
<TD class=a14>int main(){ </TD></TR></TBODY></TABLE>
<TABLE align=center width=620>
<TBODY>
<TR>
<TD class=a14>key_t key; </TD></TR></TBODY></TABLE>
<TABLE align=center width=620>
<TBODY>
<TR>
<TD class=a14>int shmid,semid; </TD></TR></TBODY></TABLE>
<TABLE align=center width=620>
<TBODY>
<TR>
<TD class=a14>char* shm; </TD></TR></TBODY></TABLE>
<TABLE align=center width=620>
<TBODY>
<TR>
<TD class=a14>char msg[7]=" data " ; </TD></TR></TBODY></TABLE>
<TABLE align=center width=620>
<TBODY>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -