﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>IT博客-tarius.wu-文章分类-UNIX</title><link>http://www.cnitblog.com/tarius.wu/category/45.html</link><description>Spend more time with your family and friends, eat your favorite foods, visit the places you love.</description><language>zh-cn</language><lastBuildDate>Sun, 09 Oct 2011 03:11:14 GMT</lastBuildDate><pubDate>Sun, 09 Oct 2011 03:11:14 GMT</pubDate><ttl>60</ttl><item><title>UNIX SOCKET编程简介</title><link>http://www.cnitblog.com/tarius.wu/articles/434.html</link><dc:creator>tarius.wu's Blog</dc:creator><author>tarius.wu's Blog</author><pubDate>Fri, 17 Jun 2005 08:46:00 GMT</pubDate><guid>http://www.cnitblog.com/tarius.wu/articles/434.html</guid><wfw:comment>http://www.cnitblog.com/tarius.wu/comments/434.html</wfw:comment><comments>http://www.cnitblog.com/tarius.wu/articles/434.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cnitblog.com/tarius.wu/comments/commentRss/434.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/tarius.wu/services/trackbacks/434.html</trackback:ping><description><![CDATA[
		<h2>
				<span lang="EN-US">1</span>
				<span style="FONT-FAMILY: 黑体">．</span>
				<span lang="EN-US">Layered Model of Networking</span>
		</h2>
		<p class="MsoNormal">
				<span lang="EN-US">Socket</span>
				<span style="FONT-FAMILY: 宋体">编程的层次模型如下图所示，</span>
		</p>
		<div style="TEXT-ALIGN: center">
				<img height="201" alt="1.JPG" src="http://www.cnitblog.com/images/cnitblog_com/tarius.wu/1.JPG" width="386" border="0" />
				<br />
		</div>
		<p class="MsoNormal">
				<span style="FONT-FAMILY: 宋体">最上面是应用层，应用层下面的是</span>
				<span lang="EN-US">SOCKET API</span>
				<span style="FONT-FAMILY: 宋体">层，再下面是传输层和网络层……</span>
				<span style="FONT-FAMILY: 宋体">实际上，</span>
				<span lang="EN-US">Sockets API</span>
				<span style="FONT-FAMILY: 宋体">层并不是一个真正定义的网络层次，但却很好的描述了</span>
				<span lang="EN-US">Socket</span>
				<span style="FONT-FAMILY: 宋体">编程所处的位置和所扮演的角色。</span>
		</p>
		<p class="MsoNormal">
				<b>
						<span lang="EN-US">TCP</span>
				</b>
				<b>
						<span style="FONT-FAMILY: 宋体">状态转换图</span>
						<span lang="EN-US">
								<?xml:namespace prefix = o /?>
								<o:p>
								</o:p>
						</span>
				</b>
		</p>
		<div style="TEXT-ALIGN: center">
				<img height="445" alt="2.JPG" src="http://www.cnitblog.com/images/cnitblog_com/tarius.wu/2.JPG" width="374" border="0" />
				<br />
				<div style="TEXT-ALIGN: left">
						<h2>
								<span lang="EN-US">2</span>
								<span style="FONT-FAMILY: 黑体">．什么是</span>
								<span lang="EN-US">SOCKET</span>
								<span style="FONT-FAMILY: 黑体">？</span>
						</h2>
						<p class="MsoNormal">
								<span style="FONT-FAMILY: 宋体">简单的，</span>
								<span lang="EN-US">Socket</span>
								<span style="FONT-FAMILY: 宋体">可以被定义描述为两个应用通信通道的端点。一个</span>
								<span lang="EN-US">Socket</span>
								<span style="FONT-FAMILY: 宋体">端点可以用</span>
								<span lang="EN-US">Socket</span>
								<span style="FONT-FAMILY: 宋体">地址来描述，</span>
								<span lang="EN-US">Socket</span>
								<span style="FONT-FAMILY: 宋体">地址结构由</span>
								<span lang="EN-US">IP</span>
								<span style="FONT-FAMILY: 宋体">地址，端口和使用协议组成（</span>
								<span lang="EN-US">TCP or UDP</span>
								<span style="FONT-FAMILY: 宋体">）。</span>
						</p>
						<div style="TEXT-ALIGN: center">
								<img height="237" alt="3.JPG" src="http://www.cnitblog.com/images/cnitblog_com/tarius.wu/3.JPG" width="364" border="0" />
								<br />
								<div style="TEXT-ALIGN: left">
										<h2>
												<span lang="EN-US" style="LINE-HEIGHT: 173%">3</span>
												<span style="LINE-HEIGHT: 173%; FONT-FAMILY: 黑体">．</span>
												<span lang="EN-US">Socket</span>
												<span style="FONT-FAMILY: 黑体">地址结构</span>
										</h2>
										<p class="MsoNormal" style="TEXT-INDENT: 21pt">
												<span style="FONT-FAMILY: 宋体">网络中以主机</span>
												<span lang="EN-US">IP</span>
												<span style="FONT-FAMILY: 宋体">、端口以及使用的协议表明一个网络应用。</span>
												<span lang="EN-US">UNIX Socket</span>
												<span style="FONT-FAMILY: 宋体">将它们组成一个结构，统称为</span>
												<span lang="EN-US">SOCKET</span>
												<span style="FONT-FAMILY: 宋体">地址结构。</span>
										</p>
										<h3>
												<span lang="EN-US">3.1<span>  </span>IPv4</span>
												<span style="FONT-FAMILY: 宋体">对应的</span>
												<span lang="EN-US">SOCKET</span>
												<span style="FONT-FAMILY: 宋体">地址结构</span>
										</h3>
										<p class="MsoNormal">
												<span style="FONT-FAMILY: 宋体">通常也称为“网际</span>
												<span lang="EN-US">SOCKET</span>
												<span style="FONT-FAMILY: 宋体">地址结构”，以“</span>
												<span lang="EN-US" style="BACKGROUND: rgb(217,217,217) 0% 50%; moz-background-clip: initial; moz-background-origin: initial; moz-background-inline-policy: initial">socketaddr_in</span>
												<span style="FONT-FAMILY: 宋体">”命名，定义在头文件</span>
												<span lang="EN-US" style="BACKGROUND: rgb(217,217,217) 0% 50%; moz-background-clip: initial; moz-background-origin: initial; moz-background-inline-policy: initial">&lt;netinet/in.h&gt;</span>
												<span style="FONT-FAMILY: 宋体">中。</span>
										</p>
										<img height="226" alt="4.JPG" src="http://www.cnitblog.com/images/cnitblog_com/tarius.wu/4.JPG" width="551" border="0" />
										<br />
										<p class="MsoNormal">
												<b>
														<span style="FONT-FAMILY: 宋体">所涉及到的数据类型：</span>
														<span lang="EN-US">
																<o:p>
																</o:p>
														</span>
												</b>
										</p>
										<img height="209" alt="5.JPG" src="http://www.cnitblog.com/images/cnitblog_com/tarius.wu/5.JPG" width="513" border="0" />
										<br />
										<h3>
												<span lang="EN-US">3.2<span>  </span>IPv6</span>
												<span style="FONT-FAMILY: 宋体">对应的</span>
												<span lang="EN-US">SOCKET</span>
												<span style="FONT-FAMILY: 宋体">地址结构</span>
										</h3>
										<img height="275" alt="6.JPG" src="http://www.cnitblog.com/images/cnitblog_com/tarius.wu/6.JPG" width="561" border="0" />
										<br />
										<h3>
												<span lang="EN-US">3.3 <span> </span></span>
												<span style="FONT-FAMILY: 宋体">通用地址结构</span>
										</h3>
										<p class="MsoNormal">
												<span lang="EN-US">
														<o:p> </o:p>
												</span>
										</p>
										<p class="MsoNormal">
												<span style="FONT-FAMILY: 宋体">当地址结构作为传递给任何一个</span>
												<span lang="EN-US">SOCKET</span>
												<span style="FONT-FAMILY: 宋体">函数的参数时，任意一个</span>
												<span lang="EN-US">Socket</span>
												<span style="FONT-FAMILY: 宋体">函数必须能处理每一种地址结构，为了解决这个问题，提出了使用通用套接口地址结构。当任何一个地址结构要作为指针参数传到套接口函数时，必须要显示转化为通用地址结构。</span>
										</p>
										<p class="MsoNormal">
												<span style="FONT-FAMILY: 宋体">在</span>
												<span lang="EN-US">IPv4</span>
												<span style="FONT-FAMILY: 宋体">应用中，使用的通用地址结构为</span>
												<span lang="EN-US" style="BACKGROUND: rgb(217,217,217) 0% 50%; moz-background-clip: initial; moz-background-origin: initial; moz-background-inline-policy: initial">struct sockaddr, </span>
												<span style="FONT-FAMILY: 宋体">定义在</span>
												<span lang="EN-US" style="BACKGROUND: rgb(217,217,217) 0% 50%; moz-background-clip: initial; moz-background-origin: initial; moz-background-inline-policy: initial">&lt;sys/socket.h&gt;</span>
												<span style="FONT-FAMILY: 宋体">中，</span>
										</p>
										<img height="86" alt="7.JPG" src="http://www.cnitblog.com/images/cnitblog_com/tarius.wu/7.JPG" width="520" border="0" />
										<br />
										<p class="MsoNormal">
												<span style="FONT-FAMILY: 宋体">例如：</span>
										</p>
										<img height="83" alt="8.JPG" src="http://www.cnitblog.com/images/cnitblog_com/tarius.wu/8.JPG" width="536" border="0" />
										<br />
										<p class="MsoNormal">
												<span style="FONT-FAMILY: 宋体">在</span>
												<span lang="EN-US">IPv6</span>
												<span style="FONT-FAMILY: 宋体">中，提出了一种新的通用地址结构：</span>
												<tt>
														<span lang="EN-US" style="FONT-SIZE: 12pt; BACKGROUND: rgb(217,217,217) 0% 50%; moz-background-clip: initial; moz-background-origin: initial; moz-background-inline-policy: initial">struct sockaddr_storage </span>
												</tt>
												<tt>
														<span style="FONT-SIZE: 12pt">定义在<span lang="EN-US" style="BACKGROUND: rgb(217,217,217) 0% 50%; moz-background-clip: initial; moz-background-origin: initial; moz-background-inline-policy: initial">&lt;netinet/in.h&gt;</span>中。<span lang="EN-US"><o:p></o:p></span></span>
												</tt>
										</p>
										<img height="168" alt="9.JPG" src="http://www.cnitblog.com/images/cnitblog_com/tarius.wu/9.JPG" width="671" border="0" />
										<br />
										<p class="MsoNormal">
												<b>
														<span lang="EN-US">struct sockaddr</span>
												</b>
												<span lang="EN-US">
												</span>
												<span style="FONT-FAMILY: 宋体">和</span>
												<tt>
														<b>
																<span lang="EN-US" style="FONT-SIZE: 12pt">struct sockaddr_storage </span>
														</b>
												</tt>
												<tt>
														<span style="FONT-SIZE: 12pt">的区别<span lang="EN-US"><o:p></o:p></span></span>
												</tt>
										</p>
										<p class="MsoNormal" style="MARGIN-LEFT: 18pt; TEXT-INDENT: -18pt">&lt;!--[if !supportLists]--&gt;<tt><span lang="EN-US" style="FONT-SIZE: 12pt"><span>a．</span></span></tt>&lt;!--[endif]--&gt;<tt><b><span lang="EN-US" style="FONT-SIZE: 12pt">struct sockaddr_storage</span></b></tt><tt><span style="FONT-SIZE: 12pt">能提供严格的结构对齐<span lang="EN-US"><o:p></o:p></span></span></tt></p>
										<p class="MsoNormal" style="MARGIN-LEFT: 18pt; TEXT-INDENT: -18pt">&lt;!--[if !supportLists]--&gt;<span lang="EN-US"><span>b．<span style="FONT: 7pt 'Times New Roman'; font-size-adjust: none; font-stretch: normal">  </span></span></span>&lt;!--[endif]--&gt;<tt><b><span lang="EN-US" style="FONT-SIZE: 12pt">struct sockaddr_storage</span></b></tt><tt><span style="FONT-SIZE: 12pt">能容纳系统支持的更大的地址结构</span></tt></p>
										<h3>
												<span lang="EN-US">3.4 <span> </span>Socket</span>
												<span style="FONT-FAMILY: 宋体">地址结构的比较</span>
										</h3>
										<img height="407" alt="a.JPG" src="http://www.cnitblog.com/images/cnitblog_com/tarius.wu/a.JPG" width="528" border="0" />
										<br />
										<h2>
												<span lang="EN-US">4</span>
												<span style="FONT-FAMILY: 黑体">．</span>
												<span lang="EN-US">Client/Server Model</span>
										</h2>
										<p class="MsoNormal">
												<span lang="EN-US">Client/Server </span>
												<span style="FONT-FAMILY: 宋体">的网络通信模型是使用最广最为基础的通信模型。在</span>
												<span lang="EN-US">Socket API</span>
												<span style="FONT-FAMILY: 宋体">环境，其应用可以归纳为：</span>
										</p>
										<div style="TEXT-ALIGN: center">
												<img height="368" alt="b.JPG" src="http://www.cnitblog.com/images/cnitblog_com/tarius.wu/b.JPG" width="376" border="0" />
												<br />
												<div style="TEXT-ALIGN: left">
														<p class="MsoNormal">
																<b>
																		<span lang="EN-US">TCP</span>
																</b>
																<b>
																		<span style="FONT-FAMILY: 宋体">链接建立</span>
																		<span lang="EN-US">
																				<o:p>
																				</o:p>
																		</span>
																</b>
														</p>
														<p class="MsoNormal">
																<span style="FONT-FAMILY: 宋体">根据</span>
																<span lang="EN-US">TCP/IP</span>
																<span style="FONT-FAMILY: 宋体">协议，函数</span>
																<span lang="EN-US">connect()</span>
																<span style="FONT-FAMILY: 宋体">激发</span>
																<span lang="EN-US">TCP</span>
																<span style="FONT-FAMILY: 宋体">的三路握手过程。</span>
														</p>
														<p class="MsoNormal">
																<span style="FONT-FAMILY: 宋体">客户端给服务器一个</span>
																<span lang="EN-US">SYN(J)</span>
																<span style="FONT-FAMILY: 宋体">信号，服务器返回一个</span>
																<span lang="EN-US">ACK(J+1); </span>
																<span style="FONT-FAMILY: 宋体">然后服务器给客户端一个</span>
																<span lang="EN-US">SYN(K),</span>
																<span style="FONT-FAMILY: 宋体">客户端也同样给服务器一个</span>
																<span lang="EN-US">ACK(K+1)</span>
																<span style="FONT-FAMILY: 宋体">，这样就算</span>
																<span lang="EN-US">connect</span>
																<span style="FONT-FAMILY: 宋体">成功。</span>
														</p>
														<p class="MsoNormal">
																<span style="FONT-FAMILY: 宋体">注意：服务器返回的</span>
																<span lang="EN-US">SYN(K)</span>
																<span style="FONT-FAMILY: 宋体">和</span>
																<span lang="EN-US">ACK(J+1)</span>
																<span style="FONT-FAMILY: 宋体">是放在同一个分节中发给客户端的，因此链路在建立连接时只用了三个分节，故称为三路握手。</span>
														</p>
														<img height="231" alt="c.JPG" src="http://www.cnitblog.com/images/cnitblog_com/tarius.wu/c.JPG" width="503" border="0" />
														<br />
														<p class="MsoNormal">
																<b>
																		<span lang="EN-US">TCP</span>
																</b>
																<b>
																		<span style="FONT-FAMILY: 宋体">链接终止</span>
																		<span lang="EN-US">
																				<o:p>
																				</o:p>
																		</span>
																</b>
														</p>
														<p class="MsoNormal">
																<span lang="EN-US">TCP</span>
																<span style="FONT-FAMILY: 宋体">用三个分节建立一个链接，而终止连接时需要四个分节。原因在于被动关闭链接一方需要关闭处理时间，因此</span>
																<span lang="EN-US">ACK</span>
																<span style="FONT-FAMILY: 宋体">和</span>
																<span lang="EN-US">FIN</span>
																<span style="FONT-FAMILY: 宋体">不能同时发给主动关闭一方。</span>
														</p>
														<img height="276" alt="d.JPG" src="http://www.cnitblog.com/images/cnitblog_com/tarius.wu/d.JPG" width="542" border="0" />
														<br />
														<p class="MsoNormal">
																<span style="FONT-FAMILY: 宋体">主动关闭一方在收到</span>
																<span lang="EN-US">ACK</span>
																<span style="FONT-FAMILY: 宋体">后，在等待被动关闭方发</span>
																<span lang="EN-US">FIN</span>
																<span style="FONT-FAMILY: 宋体">消息这一状态称为处于</span>
																<span lang="EN-US">TIME_WAIT </span>
																<span style="FONT-FAMILY: 宋体">状态。</span>
														</p>
														<h2>
																<span lang="EN-US">5 Socket API</span>
																<span style="FONT-FAMILY: 黑体">描述</span>
														</h2>
														<h3>
																<span lang="EN-US">5.1</span>
																<span style="FONT-FAMILY: 宋体">创建套接字——</span>
																<span lang="EN-US">socket</span>
																<span style="FONT-FAMILY: 宋体">函数</span>
														</h3>
														<p class="MsoNormal">
																<span style="FONT-FAMILY: 宋体">应用程序在使用套接字前，必须拥有一个套接字，系统调用</span>
																<span lang="EN-US">socket</span>
																<span style="FONT-FAMILY: 宋体">（）向应用程序提供</span>
														</p>
														<p class="MsoNormal">
																<span style="FONT-FAMILY: 宋体">创建套接字的手段，其调用格式如下：</span>
														</p>
														<img height="89" alt="e.JPG" src="http://www.cnitblog.com/images/cnitblog_com/tarius.wu/e.JPG" width="800" border="0" />
														<br />
												</div>
										</div>
										<p class="MsoNormal" style="TEXT-INDENT: 21pt">
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">参数</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">family</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">指定通信发生的区域，</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">UNIX</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">系统支持的地址族有：</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">AF_UNIX,AF_INET,AF_NS</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">等，而</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">DOS</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">、</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">WINDOWS</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">中仅支持</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">AF_INET</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">，它是网际网区域。因此，地址族与协议族相同。</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">
														<o:p>
														</o:p>
												</span>
										</p>
										<p class="MsoNormal" style="TEXT-INDENT: 21pt">
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">参数</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">type</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">描述要建立的套接字的类型。参数</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">protocol</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">说明该套接字使用的特定协议，如果调用者不希望特别指定使用的协议，则置为</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">0</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">，使用默认的连接模式。根据这</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">3</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">个参数建立一个套接字，并将相应的资源分配给它，同时返回一个整型套接字号。因此，</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">socket</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">（）系统调用实际上指定了</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">"</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">协议</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">"</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">。</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">
														<o:p>
														</o:p>
												</span>
										</p>
										<img height="211" alt="f.JPG" src="http://www.cnitblog.com/images/cnitblog_com/tarius.wu/f.JPG" width="537" border="0" />
										<br />
										<br />
										<h3>
												<span lang="EN-US">5.2</span>
												<span style="FONT-FAMILY: 宋体">指定本地址——</span>
												<span lang="EN-US">bind </span>
												<span style="FONT-FAMILY: 宋体">函数</span>
										</h3>
										<p class="MsoNormal" style="TEXT-INDENT: 21pt">
												<span style="FONT-FAMILY: 宋体">一个套接字用</span>
												<span lang="EN-US">socket</span>
												<span style="FONT-FAMILY: 宋体">（）创建后，存在一个名字空间（地址族），但它没有被命名。</span>
												<span lang="EN-US">Bind</span>
												<span style="FONT-FAMILY: 宋体">（）将套接字地址（包括本地主机地址和本断口地址）与所创建的套接字号联系起来，即将，名字赋予套接字，以指定本地半相关。其调用格式如下：</span>
										</p>
										<img height="88" alt="g.JPG" src="http://www.cnitblog.com/images/cnitblog_com/tarius.wu/g.JPG" width="799" border="0" />
										<br />
										<p class="MsoNormal" style="TEXT-INDENT: 21pt">
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">参数</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">socketfd</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">是由</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">socket()</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">调用返回的并且未作连接的套接字描述符（套接字号）。参数</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">myaddr</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">是赋给套接字</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">socketfd </span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">的本地地址（名字），其长度可变，结构随通信域的不同而不同。</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">addrlen</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">表明了</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">name</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">的长度。</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">
														<o:p>
														</o:p>
												</span>
										</p>
										<p class="MsoNormal" style="TEXT-INDENT: 21pt">
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">进程可以把一个特定的</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">IP</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">地址捆绑到它的套接口上，但此</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">IP</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">地址必须是主机的一个接口。对于</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">TCP</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">客户端，这就为在此套接口上发送的</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">IP</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">数据包分配了源</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">IP</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">地址。对于服务器端，这样做就限制了套接口只接收来自那些目的地址为此</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">IP</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">地址的客户链接。</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">
														<o:p>
														</o:p>
												</span>
										</p>
										<p class="MsoNormal" style="TEXT-INDENT: 21pt">
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">对于</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">TCP</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">，调用函数</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">bind</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">可以指定一个端口号，指定一个</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">IP</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">地址，可以两者都指定，也可以一个都不指定。对于服务器，一般指定众所周知的端口号。而不指定具体的</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">IP</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">地址。如果</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">TCP</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">服务器不把地址绑到套接口上，那么内核就把客户所发</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">SYN</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">所在分组的目的</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">IP</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">地址作为服务器的源</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">IP</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">地址。</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">
														<o:p>
														</o:p>
												</span>
										</p>
										<p class="MsoNormal" style="TEXT-INDENT: 21pt">
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">若指定端口号为</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">0</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">，则调用函数</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">bind</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">时，内核选择一个临时端口；但若指定一个通配</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">IP</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">地址，则直到套接口以连接</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">(TCP)</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">或数据报已在套接口上发出</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">(UDP),</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">内核才选择一个本地</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">IP</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">。</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">
														<o:p>
														</o:p>
												</span>
										</p>
										<p class="MsoNormal" style="TEXT-INDENT: 21pt">
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">注意到在第四部分图中，客户端并没有调用</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">bind</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">函数，因为对于客户端来说，没有必要指定具体的</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">IP</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">和端口，如果需要，内核会选择一个源</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">IP</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">地址和一个临时的端口。</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">
														<o:p>
														</o:p>
												</span>
										</p>
										<img height="154" alt="h.JPG" src="http://www.cnitblog.com/images/cnitblog_com/tarius.wu/h.JPG" width="556" border="0" />
										<br />
										<h3>
												<span lang="EN-US">5.3 connect</span>
												<span style="FONT-FAMILY: 宋体">函数</span>
										</h3>
										<p class="MsoNormal">
												<span lang="EN-US">TCP</span>
												<span style="FONT-FAMILY: 宋体">客户用</span>
												<span lang="EN-US">connect()</span>
												<span style="FONT-FAMILY: 宋体">函数建立一个与</span>
												<span lang="EN-US">TCP</span>
												<span style="FONT-FAMILY: 宋体">服务器的链接。</span>
												<span lang="EN-US">Connect</span>
												<span style="FONT-FAMILY: 宋体">（）的调用格式如下：</span>
										</p>
										<img height="90" alt="i.JPG" src="http://www.cnitblog.com/images/cnitblog_com/tarius.wu/i.JPG" width="802" border="0" />
										<br />
										<p class="MsoNormal" style="TEXT-INDENT: 21pt">
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">参数</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">socket</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">是欲建立连接的本地套接字描述符。参数</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">servaddr</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">指出说明对方套接字地址结构指针。对方套接字地址长度由</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">addrlen</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">说明。</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">
														<o:p>
														</o:p>
												</span>
										</p>
										<p class="MsoNormal" style="TEXT-INDENT: 21pt">
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">根据</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">TCP</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">的状态转移图，函数</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">connect</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">导致从</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">CLOSED</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">状态</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">(</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">调用函数</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">socket</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">创建套接口以后就一直处于此状态</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">)</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">转到</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">SYN_SENT</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">状态，若成功转到</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">ESTABLISHED</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">状态。如果函数</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">connect</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">失败，则原先创建的套接口就不可再用，必须关闭。如要重新尝试，必须重新调用</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">socket</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">，再</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">connect</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">。</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">
														<o:p>
														</o:p>
												</span>
										</p>
										<h3>
												<span lang="EN-US">5.4 listen</span>
												<span style="FONT-FAMILY: 宋体">函数</span>
										</h3>
										<p class="MsoNormal">
												<span style="FONT-FAMILY: 宋体">函数</span>
												<span lang="EN-US">listen</span>
												<span style="FONT-FAMILY: 宋体">仅被</span>
												<span lang="EN-US">TCP</span>
												<span style="FONT-FAMILY: 宋体">服务器调用，它做两件事情：</span>
										</p>
										<p class="MsoNormal" style="MARGIN-LEFT: 21pt; TEXT-INDENT: -21pt">&lt;!--[if !supportLists]--&gt;<span lang="EN-US" style="FONT-SIZE: 9pt"><span>1.<span style="FONT: 7pt 'Times New Roman'; font-size-adjust: none; font-stretch: normal">          </span></span></span>&lt;!--[endif]--&gt;<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">当函数</span><span lang="EN-US" style="FONT-SIZE: 9pt">socket</span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">创建一个套接口时，它被假设为一个主动套接口，也就是说，它是一个将调用</span><span lang="EN-US" style="FONT-SIZE: 9pt">connect</span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">发起链接的客户套接口。函数</span><span lang="EN-US" style="FONT-SIZE: 9pt">listen</span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">将未链接的套接口转换成被动套接口，告诉内核应接受指向此套接口的链接请求。根据</span><span lang="EN-US" style="FONT-SIZE: 9pt">TCP</span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">状态转移图，函数</span><span lang="EN-US" style="FONT-SIZE: 9pt">listen</span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">导致套接口状态从</span><span lang="EN-US" style="FONT-SIZE: 9pt">CLOSED</span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">转到</span><span lang="EN-US" style="FONT-SIZE: 9pt">LISTEN</span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">。</span><span lang="EN-US" style="FONT-SIZE: 9pt"><o:p></o:p></span></p>
										<p class="MsoNormal" style="MARGIN-LEFT: 21pt; TEXT-INDENT: -21pt">&lt;!--[if !supportLists]--&gt;<span lang="EN-US" style="FONT-SIZE: 9pt"><span>2.<span style="FONT: 7pt 'Times New Roman'; font-size-adjust: none; font-stretch: normal">          </span></span></span>&lt;!--[endif]--&gt;<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">函数的第二个参数规定了内核为此套接口排队的最大链接个数。</span><span lang="EN-US" style="FONT-SIZE: 9pt"><o:p></o:p></span></p>
										<img height="89" alt="j.JPG" src="http://www.cnitblog.com/images/cnitblog_com/tarius.wu/j.JPG" width="804" border="0" />
										<br />
										<p class="MsoNormal">
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">一般而言，此函数应该在</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">socket</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">和</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">bind</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">之后，调用函数</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">accept</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">之前调用。</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">
														<o:p>
														</o:p>
												</span>
										</p>
										<p class="MsoNormal">
												<b>
														<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">参数</span>
												</b>
												<b>
														<span lang="EN-US" style="FONT-SIZE: 9pt">backlog</span>
												</b>
												<b>
														<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">的解析：</span>
												</b>
												<b>
														<span lang="EN-US" style="FONT-SIZE: 9pt">
																<o:p>
																</o:p>
														</span>
												</b>
										</p>
										<p class="MsoNormal">
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">对于给定的监听套接口</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">(listen</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">之后</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">)</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">，内核要维护两个队列：一个是处于三次握手过程中（即客户端调用</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">connect</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">，服务器端收到</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">SYN</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">，并返回</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">ACK</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">和</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">SYN</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">后，在等待客户端的</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">ACK</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">），处于</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">SYN_RCVD</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">状态；另一个是从</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">connect</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">成功，处于</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">ESTABLISHED</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">状态。</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">
														<o:p>
														</o:p>
												</span>
										</p>
										<p class="MsoNormal">
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">两个队列之和不能超过</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">backlog</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">。</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">
														<o:p>
														</o:p>
												</span>
										</p>
										<img height="280" alt="k.JPG" src="http://www.cnitblog.com/images/cnitblog_com/tarius.wu/k.JPG" width="512" border="0" />
										<br />
										<h3>
												<span lang="EN-US">5.5 accept</span>
												<span style="FONT-FAMILY: 宋体">函数</span>
										</h3>
										<p class="MsoNormal">
												<span lang="EN-US">Accept</span>
												<span style="FONT-FAMILY: 宋体">函数由</span>
												<span lang="EN-US">TCP</span>
												<span style="FONT-FAMILY: 宋体">服务器调用，从已完成连接队列头返回一个已完成的链接。若已完成队列为空，则进程睡眠（假定套接口为缺省的阻塞方式）。用于使服务器等待来自某客户进程的实际连接。</span>
										</p>
										<img height="92" alt="l.JPG" src="http://www.cnitblog.com/images/cnitblog_com/tarius.wu/l.JPG" width="800" border="0" />
										<br />
										<p class="MsoNormal">
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">参数</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">cliaddr</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">和</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">addrlen</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">用来返回链接对方进程（客户端）的协议地址。</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">
														<o:p>
														</o:p>
												</span>
										</p>
										<p class="MsoNormal">
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">若函数成功返回，返回值是一个由内核自动生成的全新的描述字，代表与客户端的链接。当我们讨论函数</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">accept</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">时，常把它的第一个参数称为监听套接口描述字（由</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">socket</span>
												<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">生成的描述字）；把它的返回值称为已连接套接口描述字。</span>
												<span lang="EN-US" style="FONT-SIZE: 9pt">
														<o:p>
														</o:p>
												</span>
										</p>
										<h1>6 Reference</h1>
										<h3>补上参考书目及一些好文章</h3>
										<span style="FONT-WEIGHT: bold">1. Windows Sockets 网络程序设计大全&#x1B; </span>
										<br />    适合于WinSock编程入门。<br /><span style="FONT-WEIGHT: bold">2. Unix Networking Programming 3rd ed  </span><br />    很经典的书呀，如果你学习Unix Socket编程，你必须买的，学习WinSock也有作用的，因为WinSock是参考的Unix Socket。<br /><span style="FONT-WEIGHT: bold">3. Windows网络编程技术&#x1B;<br /></span>    讲了Win2000下的WinSock编程，讲了TCP/IP, Netbios, IPX/SPX, ATM等在Windows下的编程，有很多代码，还有一个MS Platform SDK的东西，这可是很难得的。对了,还有QoS和Raw Socket编程的程序例子<span style="FONT-WEIGHT: bold">。<br /><br /></span></div>
						</div>
				</div>
		</div>
<img src ="http://www.cnitblog.com/tarius.wu/aggbug/434.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/tarius.wu/" target="_blank">tarius.wu's Blog</a> 2005-06-17 16:46 <a href="http://www.cnitblog.com/tarius.wu/articles/434.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>DEBIAN 下NFS服务器的安装和配置</title><link>http://www.cnitblog.com/tarius.wu/articles/326.html</link><dc:creator>tarius.wu's Blog</dc:creator><author>tarius.wu's Blog</author><pubDate>Sat, 11 Jun 2005 07:56:00 GMT</pubDate><guid>http://www.cnitblog.com/tarius.wu/articles/326.html</guid><wfw:comment>http://www.cnitblog.com/tarius.wu/comments/326.html</wfw:comment><comments>http://www.cnitblog.com/tarius.wu/articles/326.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/tarius.wu/comments/commentRss/326.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/tarius.wu/services/trackbacks/326.html</trackback:ping><description><![CDATA[
<h2><span style="font-family: 黑体;">安装</span></h2>


<p class="MsoNormal"><b style=""><span lang="EN-US">NFS</span></b><b style=""><span style="font-family: 宋体;">客户端</span><span lang="EN-US"><o:p></o:p></span></b></p>


<pre><span style="background: rgb(217, 217, 217) none repeat scroll 0% 50%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; font-size: 10.5pt;" lang="EN-US"># <span class="in">apt-get install nfs-common portmap<o:p></o:p></span></span></pre>
<pre><span class="in"><b style=""><span style="font-size: 10.5pt;" lang="EN-US">NFS</span></b></span><span class="in"><b style=""><span style="font-size: 10.5pt;">服务器端</span></b></span><b style=""><span style="font-size: 10.5pt;" lang="EN-US"><o:p></o:p></span></b></pre>
<pre><span style="background: rgb(217, 217, 217) none repeat scroll 0% 50%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; font-size: 10.5pt;" lang="EN-US"># <span class="in">apt-get install nfs-kernel-server nfs-common portmap</span><o:p></o:p></span></pre>


<h2><span style="font-family: 黑体;">配置</span></h2>


<p class="MsoNormal"><span style="font-family: 宋体;">安装好</span><span lang="EN-US">NFS</span><span style="font-family: 宋体;">服务器后，</span><span lang="EN-US">/etc</span><span style="font-family: 宋体;">下会有一个</span><span lang="EN-US">NFS</span><span style="font-family: 宋体;">的配置文件</span><span lang="EN-US">exports</span><span style="font-family: 宋体;">，初次配置时此文件是空的，需要向该文件中添加内容。此文件的格式在</span><span lang="EN-US">exports(5)</span><span style="font-family: 宋体;">中，具体可以</span><span lang="EN-US">man</span><span style="font-family: 宋体;">一下，这里举一些例子：</span></p>


<p class="MsoNormal"><span style="background: rgb(217, 217, 217) none repeat scroll 0% 50%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;" lang="EN-US">#File system to share<span style="">&nbsp;&nbsp; </span><span style="">&nbsp;&nbsp;&nbsp;</span>Allowed client hosts (optional list)<o:p></o:p></span></p>


<p class="MsoNormal"><span style="background: rgb(217, 217, 217) none repeat scroll 0% 50%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;" lang="EN-US">/usr/local<span style="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span>*.zju.edu.cn(ro,async,root_squash)<o:p></o:p></span></p>


<p class="MsoNormal"><span style="background: rgb(217, 217, 217) none repeat scroll 0% 50%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;" lang="EN-US">/var/mail<span style="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>@depts_hosts(rw,sync)<o:p></o:p></span></p>


<p class="MsoNormal"><span style="background: rgb(217, 217, 217) none repeat scroll 0% 50%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;" lang="EN-US">/var/spool/news<span style="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>10.13.72.6/12(all_squash)<o:p></o:p></span></p>


<p class="MsoNormal"><span style="background: rgb(217, 217, 217) none repeat scroll 0% 50%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; font-family: 宋体;">解释：</span><span style="background: rgb(217, 217, 217) none repeat scroll 0% 50%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;" lang="EN-US"><o:p></o:p></span></p>


<p class="MsoNormal"><span style="font-family: 宋体;">第一行是注释，，提醒</span><span lang="EN-US">exports</span><span style="font-family: 宋体;">文件的格式；</span></p>


<p class="MsoNormal"><span style="font-family: 宋体;">后面每一行都列出了要共享的文件系统以、可以访问文件系统的主机，还指定了可以访问文件系统主机的可能方式：</span></p>


<ul>
  <li><!--[if !supportLists]--><span style="font-family: Wingdings;" lang="EN-US"><span style=""></span></span><span style="font-family: 宋体;">使用通配符（</span><span style="background: rgb(217, 217, 217) none repeat scroll 0% 50%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;" lang="EN-US">*.zju.edu.cn</span><span style="font-family: 宋体;">），表示在</span><span style="background: rgb(217, 217, 217) none repeat scroll 0% 50%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;" lang="EN-US">.zju.edu.cn</span><span style="font-family: 宋体;">域中的所有主机都可以访问</span><span lang="EN-US">/usr/local</span><span style="font-family: 宋体;">文件系统；</span></li>
  <li><span style="font-family: Wingdings;" lang="EN-US"><span style=""><span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;</span></span></span><!--[endif]--><span style="font-family: 宋体;">使用</span><span lang="EN-US">NIS</span><span style="font-family: 宋体;">网络组（在</span><span lang="EN-US">NIS</span><span style="font-family: 宋体;">网络组</span><span lang="EN-US">dept_hosts</span><span style="font-family: 宋体;">中的所有主机都可以安装</span><span lang="EN-US">/var/mail</span><span style="font-family: 宋体;">文件系统）。注意，这个例子只有在使用</span><span lang="EN-US">NIS</span><span style="font-family: 宋体;">的情况下有效。</span></li>
  <li><span style="font-family: 宋体;">使用</span><span lang="EN-US">IP</span><span style="font-family: 宋体;">地址（所有</span><span lang="EN-US">IP</span><span style="font-family: 宋体;">地址在</span><span lang="EN-US">10.13.72.6/12</span><span style="font-family: 宋体;">范围内的主机都可以访问</span><span lang="EN-US">/var/spool/news</span><span style="font-family: 宋体;">）</span></li>
</ul>




<p class="MsoNormal" style="margin-left: 21pt; text-indent: -21pt;"><!--[if !supportLists]--> </p>


<p class="MsoNormal"><span style="font-family: 宋体;">每一行中还列出了一些可选项，以指明访问权限：</span></p>


<ul>
  <li><span lang="EN-US">ro: readonly; rw: readwrite; </span></li>
  <li><span lang="EN-US">async</span><span style="font-family: 宋体;">选项指定了使用</span><span lang="EN-US">NFSv3</span><span style="font-family: 宋体;">中的文件服务器向磁盘写入数据的方式，允许服务器在完成写数据之前向客户端返回结果，故是异步的。</span></li>
  <li><span lang="EN-US">Sync</span><span style="font-family: 宋体;">：可想而知，它应该在向客户端返回控制权以前就应完成数据的写入。这是</span><span lang="EN-US">NFSv2</span><span style="font-family: 宋体;">的方法。</span></li>
  <li><span lang="EN-US">root_squash: </span><span style="font-family: 宋体;">表示客户端上的</span><span lang="EN-US">root</span><span style="font-family: 宋体;">用户应该映射为服务器上的</span><span lang="EN-US">nobody</span><span style="font-family: 宋体;">用户的</span><span lang="EN-US">UID</span><span style="font-family: 宋体;">。通常在所有的</span><span lang="EN-US">NFS</span><span style="font-family: 宋体;">设置中都需要这样做，否则的话客户端上的</span><span lang="EN-US">root</span><span style="font-family: 宋体;">用户就会在服务器的输出文件系统中具有</span><span lang="EN-US">root</span><span style="font-family: 宋体;">的特权了。</span></li>
  <li><span lang="EN-US">All_squash: </span><span style="font-family: 宋体;">这个选项把</span><span lang="EN-US">root_squash</span><span style="font-family: 宋体;">扩展为所有的用户，即客户端上的所有</span><span lang="EN-US">UID</span><span style="font-family: 宋体;">都映射为服务器上的</span><span lang="EN-US">nobody</span><span style="font-family: 宋体;">用户的</span><span lang="EN-US">UID</span><span style="font-family: 宋体;">。</span></li>
</ul>










<h2><span style="font-family: 黑体;">启动</span></h2>


<p class="MsoNormal"><span style="font-family: 宋体;">在准备好共享文件后，需要启动文件服务以处理客户端请求的程序和守护进程：</span><span lang="EN-US">exportfs(8), rpc.quotad(<st1:chmetcnv unitname="C" sourcevalue="8" hasspace="False" negative="False" numbertype="1" tcsc="0" w:st="on">8c</st1:chmetcnv>),
rpc.muntd(8), rpc.nfsd(8)</span><span style="font-family: 宋体;">。启动以上这些程序和守护进程的最简单方式是运行</span><span lang="EN-US">/etc/init.d/nfs start</span><span style="font-family: 宋体;">命令（</span><span lang="EN-US">root </span><span style="font-family: 宋体;">身份）。</span></p>


<h2><span style="font-family: 黑体;">一些操作实例</span></h2>


<p class="MsoNormal" style="text-indent: 21pt;"><span lang="EN-US">Exportfs(8)</span><span style="font-family: 宋体;">命令用来维护服务器当前的共享文件系统表，这个表就是</span><span lang="EN-US">/var/lib/nfs/xtab</span><span style="font-family: 宋体;">。对于典型的</span><span lang="EN-US">NFS</span><span style="font-family: 宋体;">服务器来说，</span><span lang="EN-US">exportfs</span><span style="font-family: 宋体;">要使用</span><span lang="EN-US">-r</span><span style="font-family: 宋体;">选项开始运行，这样可以将内存中的</span><span lang="EN-US">/var/lib/nfs/xtab</span><span style="font-family: 宋体;">文件与</span><span lang="EN-US">/etc/exports</span><span style="font-family: 宋体;">文件进行同步。因此当我们对</span><span lang="EN-US">exports</span><span style="font-family: 宋体;">文件作了修改，则需要手工运行</span><span lang="EN-US">exportfs –r</span><span style="font-family: 宋体;">。注意，不要手动编辑</span><span lang="EN-US">/var/lib/nfs/xtab</span><span style="font-family: 宋体;">文件，而要使用</span><span lang="EN-US">exportfs</span><span style="font-family: 宋体;">命令。</span></p>


<p class="MsoNormal"><span lang="EN-US"><span style="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: 宋体;">还有一种情况是我们只想临时性的共享一个目录，因此不想编辑</span><span lang="EN-US">/etc/exports</span><span style="font-family: 宋体;">文件，这可以通过以下方式做到：</span></p>


<p class="MsoNormal" style="text-align: center;" align="center"><span style="background: rgb(217, 217, 217) none repeat scroll 0% 50%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;" lang="EN-US">exportfs –o
–ro 10.13.72.6: /mnt/cdrom<o:p></o:p></span></p>


<p class="MsoNormal"><span style="font-family: 宋体;">这样，</span><span lang="EN-US">cdrom</span><span style="font-family: 宋体;">的共享是临时性的，在系统重启后不再输出。当然，我们可以使用以下命令来收回</span><span lang="EN-US">cdrom</span><span style="font-family: 宋体;">的共享：</span></p>


<p class="MsoNormal" style="text-align: center;" align="center"><span style="background: rgb(217, 217, 217) none repeat scroll 0% 50%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;" lang="EN-US">exportfs –u
10.13.72.6: /mnt/cdrom<o:p></o:p></span></p>


<p class="MsoNormal"><span style="font-family: 宋体;">另一个值得注意的地方是，当我们需要增加一个共享文件系统时，在编辑好</span><span lang="EN-US">/etc/exports</span><span style="font-family: 宋体;">文件后，要使用</span><span lang="EN-US">exportfs</span><span style="font-family: 宋体;">命令进行同步。但</span><span lang="EN-US">exportfs</span><span style="font-family: 宋体;">同步命令有两个选项</span> <span lang="EN-US">–a</span><span style="font-family: 宋体;">和</span><span lang="EN-US">-r</span><span style="font-family: 宋体;">。如果当前的共享文件中存在临时的文件系统，则使用</span><span lang="EN-US">exportfs –r</span><span style="font-family: 宋体;">后，</span><span lang="EN-US">/var/lib/nfs/xtab</span><span style="font-family: 宋体;">和</span><span lang="EN-US">/etc/exports</span><span style="font-family: 宋体;">文件完全同步，导致临时共享文件系统会被系统收回。而</span><span lang="EN-US">exportfs –a</span><span style="font-family: 宋体;">命令可以保持当前共享的文件系统，只添加在</span><span lang="EN-US">/etc/exports</span><span style="font-family: 宋体;">文件中列出的所有文件系统。</span></p>


<p class="MsoNormal"><span style="font-family: 宋体;">最后，可以通过</span><span lang="EN-US">exportfs
–v</span><span style="font-family: 宋体;">（详细模式）来查看当前共享的文件系统。</span></p>


<p class="MsoNormal"><span lang="EN-US"><o:p>&nbsp;<br>
</o:p></span></p>
<h2><span lang="EN-US"><o:p>补上NFS客户端推荐的参数配置</o:p></span></h2>
<h2><span lang="EN-US"><o:p></o:p></span></h2>
<p class="MsoNormal"><span lang="EN-US"><o:p>nfsvers=3,wsize=32768,rsize=32768,rw,bg,intr,hard,tcp</o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p>参数&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 意义<br>
nfsvers=3&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp; NFSv3，默认是 NFSv2，而 NFSv4 比较复杂，不是所有内核都支持。<br>
wsize=32768 &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 设置 32K 的写缓存，对于 UDP 方式来说，8K 是推荐值。<br>
rsize=32768 &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; 设置 32K 的读缓存，对于 TCP 方式来说，32K 是推荐值。<br>
rw&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 读写方式，根据权限需要有时也设置为 ro(read only)<br>
bg&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp; 如果安装失败(服务器没有响应), 在后台一直尝试，继续发其他的安装请求<br>
hard&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; 如果服务器当机，让试图访问它的操作被阻塞，直到服务器恢复为止<br>
intr&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; 允许用户中断被阻塞的操作(并且让它们返回一条错误消息)<br>
tcp&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; 选择通过 TCP 来传输，默认的 UDP 不好。<br>
<br>
<br>
</o:p></span></p>


<img src ="http://www.cnitblog.com/tarius.wu/aggbug/326.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/tarius.wu/" target="_blank">tarius.wu's Blog</a> 2005-06-11 15:56 <a href="http://www.cnitblog.com/tarius.wu/articles/326.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>UNIX环境编程 笔记--第三章 文件I/O</title><link>http://www.cnitblog.com/tarius.wu/articles/299.html</link><dc:creator>tarius.wu's Blog</dc:creator><author>tarius.wu's Blog</author><pubDate>Tue, 07 Jun 2005 10:00:00 GMT</pubDate><guid>http://www.cnitblog.com/tarius.wu/articles/299.html</guid><wfw:comment>http://www.cnitblog.com/tarius.wu/comments/299.html</wfw:comment><comments>http://www.cnitblog.com/tarius.wu/articles/299.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/tarius.wu/comments/commentRss/299.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/tarius.wu/services/trackbacks/299.html</trackback:ping><description><![CDATA[

<h2><span style="font-family: 黑体;">第三章</span> <span style="font-family: 黑体;">文件</span><span lang="EN-US">I/O</span></h2>


<p class="MsoNormal"><span style="font-family: 宋体;">在一个操作系统上，最常见的操作是针对文件的，本章描述了在</span><span lang="EN-US">UNIX</span><span style="font-family: 宋体;">系统上对文件的操作方法及与文件相关的一些概念。</span></p>


<p class="MsoNormal"><span style="font-family: 宋体;">大多数<span lang="EN-US">UNIX</span>文件<span lang="EN-US">I/O</span>只需用到<span lang="EN-US">5</span>个函数：<span lang="EN-US">open</span>，<span lang="EN-US">read</span>、<span lang="EN-US">write</span>、<span lang="EN-US">lseek </span>以及<span lang="EN-US">close</span>（还有<span lang="EN-US">create</span>函数功能以及在<span lang="EN-US">open</span>上实现，并且可以更为方便地创建文件，故不推荐使用）。<span lang="EN-US"><o:p></o:p></span></span></p>


<h3><span lang="EN-US">3.1 </span><span style="font-family: 宋体;">文件描述符</span></h3>


<p class="MsoNormal"><span style="font-family: 宋体;">对于内核而言，所有打开的文件都由文件描述符引用，即内核根据文件描述符来定位打开的文件。文件描述符是一个非负整数，当打开一个文件或新创建一个文件时，内核向进程返回一个文件描述符。按照惯例，</span><span lang="EN-US">UNIX</span><span style="font-family: 宋体;">将文件描述符</span><span lang="EN-US">0</span><span style="font-family: 宋体;">与标准输入相结合，文件描述符</span><span lang="EN-US">1</span><span style="font-family: 宋体;">与标准输出相结合，文件描述符</span><span lang="EN-US">2</span><span style="font-family: 宋体;">同标准出错相结合。在</span><span lang="EN-US">POSIX</span><span style="font-family: 宋体;">系统中，幻数</span><span lang="EN-US">0</span><span style="font-family: 宋体;">，</span><span lang="EN-US">1</span><span style="font-family: 宋体;">，</span><span lang="EN-US">2</span><span style="font-family: 宋体;">被换成符号常数</span><span lang="EN-US">STDIN_FILENO,STDOUT_FILENO,STDERRO_FILENO</span><span style="font-family: 宋体;">。</span></p>


<h3><span lang="EN-US">3.2 </span><span style="font-family: 宋体;">操作函数</span></h3>


<p class="MsoNormal"><b style=""><span style="background: rgb(217, 217, 217) none repeat scroll 0%; font-size: 14pt; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;" lang="EN-US">open<o:p></o:p></span></b></p>


<p class="MsoNormal"><span style="font-family: 宋体;">调用</span><span lang="EN-US">open</span><span style="font-family: 宋体;">函数可以打开或创建一个文件。由</span><span lang="EN-US">open</span><span style="font-family: 宋体;">返回的文件描述符数字一定是最小的文件描述符数字。可以由</span><span style="background: rgb(217, 217, 217) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;" lang="EN-US">dup2</span><span style="font-family: 宋体;">函数指定在特定的文件描述符上打开文件。</span></p>


<p class="MsoNormal" style="margin-left: 73.5pt;"><span lang="EN-US">#include &lt;sys/types.h&gt;</span></p>


<p class="MsoNormal" style="margin-left: 73.5pt;"><span lang="EN-US">#include &lt;sys/stat.h&gt;</span></p>


<p class="MsoNormal" style="margin-left: 73.5pt;"><span lang="EN-US">#include &lt;fcntl.h&gt;</span></p>


<p class="MsoNormal" style="margin-left: 73.5pt;"><span lang="EN-US">int open(const char*pathname, int oflag,.../*, mode_t mode * / ) ;</span></p>


<p class="MsoNormal" style="margin-left: 157.5pt; text-indent: 10.5pt;"><span style="font-family: 宋体;">返回：若成功为文件描述符，若出错为</span><span lang="EN-US">- 1</span></p>


<p class="MsoNormal"><b style=""><span style="background: rgb(217, 217, 217) none repeat scroll 0%; font-size: 14pt; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;" lang="EN-US">create<o:p></o:p></span></b></p>


<p class="MsoNormal"><span style="font-family: 宋体;">也可以由</span><span style="" lang="EN-US">create</span><span style="font-family: 宋体;">函数创建一个新文件。但一般不再使用。</span><span style="" lang="EN-US"><o:p></o:p></span></p>


<p class="MsoNormal"><span style="" lang="EN-US">Create</span><span style="font-family: 宋体;">的一个不足之处是</span><span style="" lang="EN-US">create</span><span style="font-family: 宋体;">只以只读方式打开所创建的文件。</span><span style="" lang="EN-US"><o:p></o:p></span></p>


<p class="MsoNormal"><b style=""><span style="background: rgb(217, 217, 217) none repeat scroll 0%; font-size: 14pt; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;" lang="EN-US">Close<o:p></o:p></span></b></p>


<p class="MsoNormal"><span style="font-family: 宋体;">用</span><span style="" lang="EN-US">close</span><span style="font-family: 宋体;">关闭一个打开的文件。</span><span style="" lang="EN-US"><o:p></o:p></span></p>


<p class="MsoNormal" style="margin-left: 73.5pt;"><span lang="EN-US">#include &lt;unistd.h&gt;</span></p>


<p class="MsoNormal" style="margin-left: 73.5pt;"><span lang="EN-US">int close (int filedes)</span><span style="font-family: 宋体;">；</span></p>


<p class="MsoNormal"><span style="font-family: 宋体;">关闭一个文件也同时释放该进程加在该文件上的锁有记录锁。当一个进程终止时，它所有打开的文件都由内核自动关闭。很多程序都用这一功能，而不使用</span><span style="" lang="EN-US">close</span><span style="font-family: 宋体;">显示关闭打开的文件。</span><span style="" lang="EN-US"><o:p></o:p></span></p>


<p class="MsoNormal"><span style="" lang="EN-US"><o:p>&nbsp;</o:p></span></p>


<p class="MsoNormal"><b style=""><span style="background: rgb(217, 217, 217) none repeat scroll 0%; font-size: 14pt; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;" lang="EN-US">Lseek<o:p></o:p></span></b></p>


<p class="MsoNormal"><span style="font-family: 宋体;">每个打开的文件都有一个与之关联的“当前文件偏移量”。它是一个非负整数，用以度量文件从文件打开开始处的计算的偏移量。通常，文件读写都从当前文件偏移量处开始，并使位移量增加所读或写的字节数。按系统默认，当打开一个文件时，除非指定</span><span style="" lang="EN-US">O_APPEND</span><span style="font-family: 宋体;">，否则该文件偏移量被指定为</span><span style="" lang="EN-US">0</span><span style="font-family: 宋体;">。</span><span style="" lang="EN-US"><o:p></o:p></span></p>


<p class="MsoNormal"><span style="font-family: 宋体;">可以调用</span><span lang="EN-US">l s e e k</span><span style="font-family: 宋体;">显式地定位一个打开文件。</span></p>


<p class="MsoNormal" style="margin-left: 42pt;"><span lang="EN-US">#include &lt;sys/types.h&gt;</span></p>


<p class="MsoNormal" style="margin-left: 42pt;"><span lang="EN-US">#include &lt;unistd.h&gt;</span></p>


<p class="MsoNormal" style="margin-left: 42pt;"><span lang="EN-US">off_t lseek(int filedes, off_t offset, int whence) ;</span></p>


<p class="MsoNormal" style="margin-left: 168pt; text-indent: 21pt;"><span style="font-family: 宋体;">返回：若成功为新的文件位移，若出错为</span><span lang="EN-US">- 1</span></p>


<p class="MsoNormal"><b style=""><span style="background: rgb(217, 217, 217) none repeat scroll 0%; font-size: 14pt; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;" lang="EN-US">Read<o:p></o:p></span></b></p>


<p class="MsoNormal"><span style="font-family: 宋体;">用</span><span style="" lang="EN-US">read</span><span style="font-family: 宋体;">函数从一个打开的文件中读取数据。</span><span style="" lang="EN-US"><o:p></o:p></span></p>


<p class="MsoNormal" style="margin-left: 42pt;"><span lang="EN-US">#include &lt;unistd.h&gt;</span></p>


<p class="MsoNormal" style="margin-left: 42pt;"><span lang="EN-US">ssize_t read(int filedes, void *buff, size_t nbytes) ;</span></p>


<p class="MsoNormal" style="margin-left: 147pt; text-indent: 21pt;"><span style="font-family: 宋体;">返回：读到的字节数，若已到文件尾为</span><span lang="EN-US">0</span><span style="font-family: 宋体;">，若出错为</span><span lang="EN-US">- 1</span></p>


<p class="MsoNormal"><span style="background: rgb(217, 217, 217) none repeat scroll 0%; font-size: 14pt; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;" lang="EN-US">Write<o:p></o:p></span></p>


<p class="MsoNormal"><span style="font-family: 宋体;">用</span><span style="" lang="EN-US">write</span><span style="font-family: 宋体;">函数向一个打开的文件中写数据。</span><span style="" lang="EN-US"><o:p></o:p></span></p>


<p class="MsoNormal" style="margin-left: 31.5pt;"><span lang="EN-US">#include &lt;unistd.h&gt;</span></p>


<p class="MsoNormal" style="margin-left: 31.5pt;"><span lang="EN-US">ssize_t write(int filedes, const void * buff , size_t nbytes) ;</span></p>


<p class="MsoNormal" style="margin-left: 157.5pt; text-indent: 10.5pt;"><span style="font-family: 宋体;">返回：若成功为已写的字节数，若出错为</span><span lang="EN-US">- 1</span></p>


<h3><span lang="EN-US">3.3 </span><span style="font-family: 宋体;">文件共享</span></h3>


<p class="MsoNormal"><span lang="EN-US">Unix</span><span style="font-family: 宋体;">支持在不同进程间共享打开文件。每个进程都有一个记录项，该记录项记录着该进程的信息，当然要包括该进程所打开的文件，这由记录项中的文件描述符表维护。</span></p>

<img src="http://www.cnitblog.com/images/cnitblog_com/tarius.wu/file1.JPG" alt="file1.JPG" border="0" height="272" width="558"><br>


<p class="MsoNormal" style="text-align: center;" align="center"><span style="font-size: 9pt; font-family: 宋体;">图</span><span style="font-size: 9pt;" lang="EN-US">3.1<span style="">&nbsp; </span></span><span style="font-size: 9pt; font-family: 宋体;">打开文件的内核数据结构</span><span style="font-size: 9pt;" lang="EN-US"><o:p></o:p></span></p>


<p class="MsoNormal"><span style="font-family: 宋体;">由上图可知，进程表项中有文件描述符表，每一个文件描述符指向所对应文件的文件表，文件表记录着文件状态标志、当前文件位移量，而文件的物理信息，如文件名、路径、所有者以及文件大小则由</span><span style="" lang="EN-US">V</span><span style="font-family: 宋体;">节点指针指向一个</span><span style="" lang="EN-US">v</span><span style="font-family: 宋体;">节点表确定；实际上，是</span><span style="" lang="EN-US">i</span><span style="font-family: 宋体;">节点信息包含了文件的物理信息。</span><span style="" lang="EN-US"><o:p></o:p></span></p>

<img src="http://www.cnitblog.com/images/cnitblog_com/tarius.wu/file2.JPG" alt="file2.JPG" border="0" height="414" width="558"><br>


<p class="MsoNormal"><span style="font-family: 宋体;">图</span><span style="" lang="EN-US">3.2</span><span style="font-family: 宋体;">描述了两个进程各自打开同一个文件的情况。每个进程都有自己文件表项的理由是，这样可以维护各自的当前文件位移量。</span><span style="" lang="EN-US"><o:p></o:p></span></p>


<h3><span lang="EN-US">3.4 </span><span style="font-family: 宋体;">原子操作</span></h3>


<p class="MsoNormal"><span style="font-family: 宋体;">原子操作的意思是指这种操作是不可分的，否则将会带来不可预知的结果。在操作系统上，操作不可分的意思是指调度进程不应该在该操作未完成时进行进程切换。</span></p>


<p class="MsoNormal"><span style="font-family: 宋体;">如有两个进程</span><span lang="EN-US">A</span><span style="font-family: 宋体;">和</span><span lang="EN-US">B</span><span style="font-family: 宋体;">，都对同一个文件进行添加操作。</span><span lang="EN-US">A</span><span style="font-family: 宋体;">先调用</span><span lang="EN-US">lseek</span><span style="font-family: 宋体;">函数将当前文件描述符定到</span><span lang="EN-US">1500</span><span style="font-family: 宋体;">字节处（当前文件尾），但未等</span><span lang="EN-US">A</span><span style="font-family: 宋体;">开始写，内核切换进程使进程</span><span lang="EN-US">B</span><span style="font-family: 宋体;">开始执行，</span><span lang="EN-US">B</span><span style="font-family: 宋体;">也</span><span lang="EN-US">lseek</span><span style="font-family: 宋体;">到</span><span lang="EN-US">1500</span><span style="font-family: 宋体;">字节处，并调用</span><span lang="EN-US">write</span><span style="font-family: 宋体;">函数写了</span><span lang="EN-US">100</span><span style="font-family: 宋体;">字节。这样文件的长度变为</span><span lang="EN-US">1600</span><span style="font-family: 宋体;">字节，内核更新</span><span lang="EN-US">v</span><span style="font-family: 宋体;">节点信息（注意</span><span lang="EN-US">v</span><span style="font-family: 宋体;">节点信息是</span><span lang="EN-US">A</span><span style="font-family: 宋体;">和</span><span lang="EN-US">B</span><span style="font-family: 宋体;">共享的）。然后，内核又进行进程切换使进程</span><span lang="EN-US">A</span><span style="font-family: 宋体;">恢复执行，此时</span><span lang="EN-US">A</span><span style="font-family: 宋体;">调用</span><span lang="EN-US">write</span><span style="font-family: 宋体;">也写了</span><span lang="EN-US">100</span><span style="font-family: 宋体;">字节。这样的后果就是导致文件的实际内容都不是进程</span><span lang="EN-US">A</span><span style="font-family: 宋体;">和</span><span lang="EN-US">B</span><span style="font-family: 宋体;">所期望的。</span></p>


<p class="MsoNormal"><span style="font-family: 宋体;">为了解决这一问题，办法就是将</span><span lang="EN-US">lseek</span><span style="font-family: 宋体;">和</span><span lang="EN-US">write</span><span style="font-family: 宋体;">作为一个原子操作，不允许在这两个操作未完成时进行进程切换。</span><span lang="EN-US">Unix</span><span style="font-family: 宋体;">提供了这种原子操作，就是在打开文件时指定</span><span lang="EN-US">O_APPEND</span><span style="font-family: 宋体;">。</span></p>

<br>
<img src ="http://www.cnitblog.com/tarius.wu/aggbug/299.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/tarius.wu/" target="_blank">tarius.wu's Blog</a> 2005-06-07 18:00 <a href="http://www.cnitblog.com/tarius.wu/articles/299.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>UNIX系统的引导过程</title><link>http://www.cnitblog.com/tarius.wu/articles/227.html</link><dc:creator>tarius.wu's Blog</dc:creator><author>tarius.wu's Blog</author><pubDate>Mon, 30 May 2005 08:24:00 GMT</pubDate><guid>http://www.cnitblog.com/tarius.wu/articles/227.html</guid><wfw:comment>http://www.cnitblog.com/tarius.wu/comments/227.html</wfw:comment><comments>http://www.cnitblog.com/tarius.wu/articles/227.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/tarius.wu/comments/commentRss/227.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/tarius.wu/services/trackbacks/227.html</trackback:ping><description><![CDATA[<h2 style="margin: 13pt 0pt;"><span lang="EN-US"><font face="Arial">1. </font></span><span style="font-family: 黑体;">介绍</span></h2>
<p class="MsoNormal" style="margin: 0pt;"><span style="font-family: 宋体;">引导过程就是简单意义上的</span><span lang="EN-US">UNIX</span><span style="font-family: 宋体;">；通过它能看到各种不同的组件和设计模式（它们构成了</span><span lang="EN-US">UNIX</span><span style="font-family: 宋体;">的全部）。在这里我们打算看一下每次按下电源按钮之后</span><span lang="EN-US">OS</span><span style="font-family: 宋体;">是如何启动的。</span></p>
<h2 style="margin: 13pt 0pt;"><span lang="EN-US"><font face="Arial">2. </font></span><span style="font-family: 黑体;">五部引导过程概述</span></h2>
<p class="MsoNormal" style="margin: 0pt;"><span style="font-family: 宋体;">可将引导（启动）过程划分为</span><span lang="EN-US">5</span><span style="font-family: 宋体;">个主要步骤：</span></p>
<p class="MsoNormal" style="margin: 0pt 0pt 0pt 21pt; text-indent: -21pt;"><span style="" lang="EN-US"><span style="">1)<span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-family: 宋体;">固件：硬件自识别（</span><span lang="EN-US">PROM/BIOS</span><span style="font-family: 宋体;">）</span></p>
<p class="MsoNormal" style="margin: 0pt 0pt 0pt 21pt; text-indent: -21pt;"><span style="" lang="EN-US"><span style="">2)<span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span lang="EN-US">Bootloader</span><span style="font-family: 宋体;">（自举操作系统载入器）</span></p>
<p class="MsoNormal" style="margin: 0pt 0pt 0pt 21pt; text-indent: -21pt;"><span style="" lang="EN-US"><span style="">3)<span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-family: 宋体;">内核：初始化和控制转移</span></p>
<p class="MsoNormal" style="margin: 0pt 0pt 0pt 21pt; text-indent: -21pt;"><span style="" lang="EN-US"><span style="">4)<span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span lang="EN-US">Init</span><span style="font-family: 宋体;">和初始化脚本</span></p>
<p class="MsoNormal" style="margin: 0pt 0pt 0pt 21pt; text-indent: -21pt;"><span style="" lang="EN-US"><span style="">5)<span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-family: 宋体;">交给管理员：其他杂项</span></p>
<h2 style="margin: 13pt 0pt;"><span lang="EN-US"><font face="Arial">3. </font></span><span style="font-family: 黑体;">固件</span><span lang="EN-US"><font face="Arial">—</font></span><span style="font-family: 黑体;">硬件自识别</span></h2>
<p class="MsoNormal" style="margin: 0pt;"><span style="font-family: 宋体;">固件是一系列特殊的指令，介于硬件和软件层之间，负责这两者之间的相互传译。尽管听起来是一件微不足道的工作，但它实际的工作却举足轻重：固件传译的不仅是语言，它还要传译核心元素。硬件只理解电子脉冲；软件（在其最基本的级别）只理解</span><span lang="EN-US">1</span><span style="font-family: 宋体;">和</span><span lang="EN-US">0</span><span style="font-family: 宋体;">的数据流；固件是两者的一种合成，在硬件中永久地（或半永久地）嵌入了软件形式的例程。它代表了用户同计算机进行交互的最基本的级别（原始的硬件插拔动作除外）。</span></p>
<h3 style="margin: 13pt 0pt;"><font size="5"><span lang="EN-US">3.1 </span><span style="font-family: 宋体;">固件的一些实例</span></font></h3>
<p class="MsoNormal" style="margin: 0pt;"><span style="font-family: 宋体;">在同固件打交道的过程中，可能会遇到以下术语：</span></p>
<ul>
  <li><span style="font-family: Wingdings;" lang="EN-US"><span style=""><span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;</span></span></span><span lang="EN-US">BIOS</span></li>
  <li><span style="font-family: Wingdings;" lang="EN-US"><span style=""><span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;</span></span></span><span lang="EN-US">PROM/EPPROM/EEPPROM</span></li>
  <li><span style="font-family: Wingdings;" lang="EN-US"><span style=""><span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;</span></span></span><span lang="EN-US">NVRAM</span></li>
  <li><span style="font-family: Wingdings;" lang="EN-US"><span style=""><span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;</span></span></span><span lang="EN-US">CMOS</span></li>
</ul>




<p class="MsoNormal" style="margin: 0pt;"><span style="font-family: 宋体;">它们的共同特点是：</span></p>
<ul>
  <li><span style="font-family: Wingdings;" lang="EN-US"><span style=""></span></span><span style="font-family: 宋体;">所有例程都是非易失性的芯片</span></li>
  <li><span style="font-family: Wingdings;" lang="EN-US"><span style=""><span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;</span></span></span><span style="font-family: 宋体;">所有都采用与</span><span lang="EN-US">OS</span><span style="font-family: 宋体;">无关的技术。它们的设计和行动独立于其中存放的内容</span></li>
  <li><span style="font-family: Wingdings;" lang="EN-US"><span style=""><span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;</span></span></span><span style="font-family: 宋体;">都具有类似的功能：维持基本的、简单的软件和驱动程序，以及它们相关的一些参数，还提供对键盘、显示器和硬盘的基本访问</span></li>
  <li><span style="font-family: Wingdings;" lang="EN-US"><span style=""><span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;</span></span></span><span style="font-family: 宋体;">都采取了专门的设计，在出现磁盘</span><span lang="EN-US">/</span><span style="font-family: 宋体;">外设故障时，保证本身仍然可用，不会被破坏；即使不访问硬盘或移动式磁盘，它们存储的程序也能运行。</span></li>
  <li><span style="font-family: Wingdings;" lang="EN-US"><span style=""></span></span><span style="font-family: 宋体;">所有都容纳着ROM bootstrap routine(启动程序，用来读入存放于MBR处的bootloader)</span><span style="font-family: 宋体;">程序</span></li>
</ul>





<h3 style="margin: 13pt 0pt;"><font size="5"><span lang="EN-US">3.2 </span><span style="font-family: 宋体;">固件的工作</span></font></h3>
<p class="MsoNormal" style="margin: 0pt;"><span style="font-family: 宋体;">固件负责硬件的自查（查找硬件的存在），并让系统知道自己有哪些组件可用。这意味着，固件必须有相应的例程来检查连接的设备以及内建的控制器。但要注意的是：在内核装载恰当的驱动程序和模块之前，有的硬件仍是看不见的。</span></p>
<p class="MsoNormal" style="margin: 0pt;"><span style="font-family: 宋体;">标识出设备之后，会对它们的基本功能进行测试，通常用它们的内嵌例程来进行。这些步骤统称为</span><span lang="EN-US">POST—</span><span style="font-family: 宋体;">开机自检（</span><span lang="EN-US">Power-On Self-Test</span><span style="font-family: 宋体;">）。</span></p>
<p class="MsoNormal" style="margin: 0pt;"><span style="font-family: 宋体;">一旦确认并验证了系统的硬件，固件便开始搜索可引导设备</span><span lang="EN-US">—</span><span style="font-family: 宋体;">要么一个内部列表，要么用一个环境变量。</span></p>
<p class="MsoNormal" style="margin: 0pt;"><span style="font-family: 宋体;">找到一个可引导设备后，会检查它的引导扇区（或引导块），以获取更多的信息。这些信息会传给</span><span lang="EN-US">OS</span><span style="font-family: 宋体;">载入程序。</span></p>
<h2 style="margin: 13pt 0pt;"><span lang="EN-US"><font face="Arial">4. bootloader—</font></span><span style="font-family: 黑体;">载入</span><span lang="EN-US"><font face="Arial">OS</font></span></h2>
<p class="MsoNormal" style="margin: 0pt;"><span style="font-family: 宋体;">想象系统现在已被唤醒，并回答了第一个问题：“我是什么”，下一步是找到“大脑”，并回答：“我是谁？”。对于任何</span><span lang="EN-US">UNIX</span><span style="font-family: 宋体;">系统，基本身份信息都是封装在本地</span><span lang="EN-US">OS</span><span style="font-family: 宋体;">中的。</span></p>
<p class="MsoNormal" style="margin: 0pt;"><span lang="EN-US">Bootloader</span><span style="font-family: 宋体;">这个术语是“</span><span lang="EN-US">bootstrap Operating System loader</span><span style="font-family: 宋体;">”的简称，即“自举操作系统的装入器”。</span></p>
<p class="MsoNormal" style="margin: 0pt;"><span style="background: rgb(217, 217, 217) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; font-family: 宋体;">何谓“自举”</span><span style="background: rgb(217, 217, 217) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="margin: 0pt;"><span style="background: rgb(217, 217, 217) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; font-family: 宋体;">根据</span><span style="background: rgb(217, 217, 217) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;" lang="EN-US">Merriam-Webster</span><span style="background: rgb(217, 217, 217) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; font-family: 宋体;">在线字典的说法，首次使用</span><span style="background: rgb(217, 217, 217) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;" lang="EN-US">bootstrap</span><span style="background: rgb(217, 217, 217) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; font-family: 宋体;">（自举）这个术语是在</span><span style="background: rgb(217, 217, 217) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;" lang="EN-US">1926</span><span style="background: rgb(217, 217, 217) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; font-family: 宋体;">年。它的来源确实是一个人试图通过拉自己的鞋带（</span><span style="background: rgb(217, 217, 217) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;" lang="EN-US">bootstrap</span><span style="background: rgb(217, 217, 217) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; font-family: 宋体;">），从而将自己举高。这也是“自力更生”</span><span style="background: rgb(217, 217, 217) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;" lang="EN-US">(pull yourself up by your bootstrap)</span><span style="background: rgb(217, 217, 217) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; font-family: 宋体;">这一谚语的来历。</span><span style="background: rgb(217, 217, 217) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="margin: 0pt;"><span style="background: rgb(217, 217, 217) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; font-family: 宋体;">通常，“自举”意味着利用尽可能少的外部介入和资源，从而让某种东西工作起来。对计算机来说，它的自举意味着使用少量的、独立的、内部的功能，从而初始化，并将控制权交给操作系统。</span><span style="background: rgb(217, 217, 217) none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;" lang="EN-US"><o:p></o:p></span></p>
<h3 style="margin: 13pt 0pt;"><font size="5"><span lang="EN-US">4.1 bootloader</span><span style="font-family: 宋体;">的工作</span></font></h3>
<p class="MsoNormal" style="margin: 0pt;"><span lang="EN-US">Bootloader</span><span style="font-family: 宋体;">是</span><span lang="EN-US">UNIX</span><span style="font-family: 宋体;">实际启动你的系统的地方。在这里，你将启动一系列软件过程，最终将系统控制权从硬件交给</span><span lang="EN-US">OS</span><span style="font-family: 宋体;">。</span></p>
<p class="MsoNormal" style="margin: 0pt;"><span style="font-family: 宋体;">为了使</span><span lang="EN-US">bootloader</span><span style="font-family: 宋体;">能够保存到固件中，关键的一点是它尽可能小，它必须能装到磁盘的引导扇区。同时，这也意味着它必须相当简单，只需采用足够的逻辑，能够载入和运行</span><span lang="EN-US">OS</span><span style="font-family: 宋体;">引导序列的下一个程序即可。为了找到</span><span lang="EN-US">bootloader</span><span style="font-family: 宋体;">，要么对设备进行顺序搜索，要么检查由管理员提供的一个列表。注意</span><span lang="EN-US">bootloader</span><span style="font-family: 宋体;">的相关设置保存在系统固件中。</span></p>
<p class="MsoNormal" style="margin: 0pt;"><span style="font-family: 宋体;">在</span><span lang="EN-US">UNIX</span><span style="font-family: 宋体;">的世界中，会经常激将复杂的工作分解成小的，分散的任务，分别由小的，专用的程序来执行。这是</span><span lang="EN-US">UNIX</span><span style="font-family: 宋体;">十分重要的一个特点。</span></p>
<h2 style="margin: 13pt 0pt;"><span lang="EN-US"><font face="Arial">5 </font></span><span style="font-family: 黑体;">内核——初始化和控制转移</span></h2>
<p class="MsoNormal" style="margin: 0pt;"><span style="font-family: 宋体;">在</span><span lang="EN-US">UNIX</span><span style="font-family: 宋体;">世界中，有两条恒定不变的真理。首先，</span><span lang="EN-US">UNIX</span><span style="font-family: 宋体;">中存在的任何东西都是一个文件；其次，</span><span lang="EN-US">UNIX</span><span style="font-family: 宋体;">中发生的任何事情都是一个进程。内核是一个编译好的可执行文件，在外观上同其他的可执行文件没什么区别。但只要在引导期间把它装入内存，它就开始控制其他所有系统进程和进程调度器——换句话说，它控制着发生的一切事情。</span></p>
<p class="MsoNormal" style="margin: 0pt;"><span style="font-family: 宋体;">然而，“控制一切事情”并不意味着“做一切事情”——这是非常重要的区别。内核实际上能做的事情是非常有限的。</span></p>
<p class="MsoNormal" style="margin: 0pt;"><span style="font-family: 宋体;">现在我们称内核是一个文件，但文件的位置却是不定的。事实上文件完全可能存在一个远程服务器上，根本不在你的系统中。但就实际用途来说，内核在哪里并不重要，只要能找到并载入它即可。</span></p>
<p class="MsoNormal" style="margin: 0pt;"><span style="font-family: 宋体;">为简化讨论，我们认为在引导阶段最常见的下一个步骤是：载入存放在本地硬盘上的一个本地内核。</span></p>
<h3 style="margin: 13pt 0pt;"><font size="5"><span lang="EN-US">5.1 </span><span style="font-family: 宋体;">内核的工作</span></font></h3>
<p class="MsoNormal" style="margin: 0pt;"><span style="font-family: 宋体;">内核为</span><span lang="EN-US">UNIX</span><span style="font-family: 宋体;">系统中发生的其他一切事情提供了环境。它是一个基本框架，来自文件系统的任何其他命令都要布置其中。它构建了一个虚拟机，硬件和软件在此相会交互。内核负责处理所有系统资源的分配，包括内存、虚拟内存、</span><span lang="EN-US">CPU</span><span style="font-family: 宋体;">时间共享、交换和分页；它还负责系统内部的通信，不管是在软件进程之间还是在软件到硬件指令之间。为了对后者进行管理，内核可提供永久存储空间的访问渠道——包括硬盘及其文件。</span></p>
<p class="MsoNormal" style="margin: 0pt;"><span style="font-family: 宋体;">文件（包括内核及其附属内容）保存在一种随机存储的介质上，由文件系统对其进行结构化和管理。文件系统必须逻辑地装入，以便系统能够进行文件存取。当然，和系统中的其他任何东西一样，最终都是由内核来控制文件系统。</span></p>
<p class="MsoNormal" style="margin: 0pt;"><span style="font-family: 宋体;">这听起来似乎是一个先有鸡还是先有蛋的问题：你要先有文件系统才能装入内核；但除非你有一个内核，否则无法装入文件系统</span><span lang="EN-US">…</span><span style="font-family: 宋体;">这里的诀窍在于，</span><span lang="EN-US">bootloader</span><span style="font-family: 宋体;">会在适当的时候介入，由它装入恰当的文件系统，以便</span><span lang="EN-US">OS</span><span style="font-family: 宋体;">能够正确地载入和接管。</span></p>
<h2 style="margin: 13pt 0pt;"><span lang="EN-US"><font face="Arial">6 init</font></span><span style="font-family: 黑体;">进程和初始化脚本</span></h2>
<p class="MsoNormal" style="margin: 0pt;"><span style="font-family: 宋体;">现在，内核已经装入。系统已经准备好回答这样一个问题：“现在做什么？”随后，要由</span><span lang="EN-US">init</span><span style="font-family: 宋体;">进程来回答这一问题。创建</span><span lang="EN-US">init</span><span style="font-family: 宋体;">进程是在引导过程中内核直接进行的最后一项干预。</span></p>
<p class="MsoNormal" style="margin: 0pt;"><span lang="EN-US">Init</span><span style="font-family: 宋体;">启动时，它会执行各个默认启动例程，从而继续引导过程（包括检查和装入文件系统、启动守护进程等）。在一个正常运行的</span><span lang="EN-US">UNIX</span><span style="font-family: 宋体;">系统中，</span><span lang="EN-US">init</span><span style="font-family: 宋体;">是第一个可以存在的进程。正因为如此，它的进程</span><span lang="EN-US">ID</span><span style="font-family: 宋体;">肯定是</span><span lang="EN-US">1</span><span style="font-family: 宋体;">。</span></p>
<h3 style="margin: 13pt 0pt;"><font size="5"><span lang="EN-US">6.1 init</span><span style="font-family: 宋体;">的工作</span></font></h3>
<p class="MsoNormal" style="margin: 0pt;"><span lang="EN-US">Init</span><span style="font-family: 宋体;">进程负责所有的核心系统功能的有序启动（和关闭），这些功能位于内核之外。为此，它必须有能力创建（或孵化</span><span lang="EN-US">spawn</span><span style="font-family: 宋体;">）大量进程。</span></p>
<h3 style="margin: 13pt 0pt;"><font size="5"><span lang="EN-US">6.2 init</span><span style="font-family: 宋体;">的机制和特点：</span><span lang="EN-US">inittab</span></font></h3>
<p class="MsoNormal" style="margin: 0pt;"><span style="font-family: 宋体;">当然，</span><span lang="EN-US">init</span><span style="font-family: 宋体;">仅仅孵化进程是不够的——它们还必须为进程赋予权限。这正是管理员真正能控制的第一个项目：取决于系统用什么“运行级别”</span><span lang="EN-US">(runlevel)</span><span style="font-family: 宋体;">或者说“运行模式”来工作。它们会表现出不同的行为。</span></p>
<p class="MsoNormal" style="margin: 0pt;"><span style="font-family: 宋体;">在</span><span lang="EN-US">inittab</span><span style="font-family: 宋体;">中，所有条目采取如下格式：</span></p>
<p class="MsoNormal" style="margin: 0pt;"><span lang="EN-US">id: run-level : action : process</span></p>
<p class="MsoNormal" style="margin: 0pt;"><span style="font-family: 宋体;">第一个字段</span><span lang="EN-US">id</span><span style="font-family: 宋体;">是条目的标志符。</span></p>
<p class="MsoNormal" style="margin: 0pt;"><span style="font-family: 宋体;">第二个字段指运行级别。指该进程能在哪一个运行级别上被启动。一般</span><span lang="EN-US">UNIX</span><span style="font-family: 宋体;">的运行级别有</span><span lang="EN-US">0~9</span><span style="font-family: 宋体;">个级别，在</span><span lang="EN-US">run-level</span><span style="font-family: 宋体;">字段上看可以用多个运行级别的组合，如</span><span lang="EN-US">023</span><span style="font-family: 宋体;">。</span></p>
<p class="MsoNormal" style="margin: 0pt;"><span style="font-family: 宋体;">第三个字段描述了你想让系统做什么事情。一些比较常用的值有：</span></p>
<ul>
  <li><span style="font-family: Wingdings;" lang="EN-US"><span style=""><span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;</span></span></span><span lang="EN-US">Boot</span><span style="font-family: 宋体;">——只在系统引导时运行进程</span></li>
  <li><span style="font-family: Wingdings;" lang="EN-US"><span style=""></span></span><span lang="EN-US">Once</span><span style="font-family: 宋体;">——只有进入指定的运行级别后才运行进程</span></li>
  <li><span style="font-family: Wingdings;" lang="EN-US"><span style=""><span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;</span></span></span><span lang="EN-US">Respawn</span><span style="font-family: 宋体;">——一旦进程终止，便重新启动进程</span></li>
  <li><span style="font-family: Wingdings;" lang="EN-US"><span style=""></span></span><span lang="EN-US">Wait</span><span style="font-family: 宋体;">——类似于</span><span lang="EN-US">once</span><span style="font-family: 宋体;">，但在继续前，会等待进程结束。</span></li>
</ul>




<p class="MsoNormal" style="margin: 0pt;"><span style="font-family: 宋体;">第四个字段指定了要运行的可执行程序的完整路径，以及应传递给它的任意参数（只能用空格分隔）。</span></p>
<p class="MsoNormal" style="margin: 0pt;"><span lang="EN-US"><o:p>&nbsp;</o:p></span></p><img src ="http://www.cnitblog.com/tarius.wu/aggbug/227.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/tarius.wu/" target="_blank">tarius.wu's Blog</a> 2005-05-30 16:24 <a href="http://www.cnitblog.com/tarius.wu/articles/227.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>