<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>不敢流泪 &#187; linux</title>
	<atom:link href="http://www.boluor.com/tag/linux/feed" rel="self" type="application/rss+xml" />
	<link>http://www.boluor.com</link>
	<description></description>
	<lastBuildDate>Fri, 07 Oct 2011 07:28:40 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>[virtualbox]windows宿主机访问linux客户机</title>
		<link>http://www.boluor.com/virtualbox-windows-host-connect-linux-guest.html</link>
		<comments>http://www.boluor.com/virtualbox-windows-host-connect-linux-guest.html#comments</comments>
		<pubDate>Wed, 05 May 2010 15:40:57 +0000</pubDate>
		<dc:creator>boluor</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[virtualbox]]></category>

		<guid isPermaLink="false">http://www.boluor.com/?p=630</guid>
		<description><![CDATA[<p>　　今天felix建议，可以虚拟机里跑个ubuntu server，就没必要跑ubuntu下开发，再回到windows下写论文了。之前有考虑过，但是1G的内存，跑了个win7还开了Aero，担心内存不够。回来把Aero给关了，装了试试，有点卡，不过将就着能用，早该加内存了。</p>
<p>　　客户机跑ubuntu 10.04 server，NAT连接的网络。NAT engine将宿主机当作了路由器，所有流出和流进虚拟机的数据包都由这个engine转发，但是这样，客户机隐藏在幕后，包括宿主机在内的其他主机都访问不到客户机了。VirtualBox的帮助文件中提到，如果想在客户机上跑一些服务，就需要用NAT端口映射。使用V&#8230;</p>]]></description>
			<content:encoded><![CDATA[<p>　　今天felix建议，可以虚拟机里跑个ubuntu server，就没必要跑ubuntu下开发，再回到windows下写论文了。之前有考虑过，但是1G的内存，跑了个win7还开了Aero，担心内存不够。回来把Aero给关了，装了试试，有点卡，不过将就着能用，早该加内存了。</p>
<p>　　客户机跑ubuntu 10.04 server，NAT连接的网络。NAT engine将宿主机当作了路由器，所有流出和流进虚拟机的数据包都由这个engine转发，但是这样，客户机隐藏在幕后，包括宿主机在内的其他主机都访问不到客户机了。VirtualBox的帮助文件中提到，如果想在客户机上跑一些服务，就需要用NAT端口映射。使用VBoxManage.exe可以满足需求。如果要想开启ssh server，好使宿主机可以用putty或者SecureCRT等等连上去开发，可以用下面的命令(cmd下并切换到virtualbox的安装目录即VBoxManage所在的目录下)：</p>
<p>(1)　　VBoxManage setextradata [GuestHostName] “VBoxInternal/Devices/[vcard]/0/LUN#0/Config/[servicename]/Protocol” TCP<br />
(2)　　VBoxManage setextradata [GuestHostName] “VBoxInternal/Devices/[vcard]/0/LUN#0/Config/[servicename]/GuestPort” 22<br />
(3)　　VBoxManage setextradata [GuestHostName] “VBoxInternal/Devices/[vcard]/0/LUN#0/Config/[servicename]/HostPort” [specifiededport]</p>
<p>其中：<br />
[GuestHostName]为客户机的名称，比如ubuntuserver，如果有空格的话用”"括起来<br />
[vcard]需要根据客户机的网卡芯片改变。PCNet -> pcnet；Intel PRO/1000 -> e1000；<br />
[servicename]就是为这个转发设置起个名字，随便就可以~别跟其他转发设置起冲突<br />
[specifiededport]是将客户机22端口映射到主机的哪个端口，这个端口号最好>1024.</p>
<p>注意设置的时候关闭虚拟机或者是保存状态.</p>
<p>如果要开启其他服务的话，就按照这种格式。比如换成http，mysql时，Protocol不变，只需设置GuestPort为对应的端口号.(ssh -> 22,mysql -> 3306,etc)</p>
<p>在windows宿主机中打开localhost，客户机的Http服务器就会响应了。在SecureCRT用ssh连接localhost时，别忘了将端口号设置为你定义的端口号^/^</p>
<p>不过每次系统启动的时候就需要重新设置下，可以扔到一个bat文件中，开机启动或者virtualbox启动时执行。</p>
<p>由于安装的是ubuntu server ,VBoxGuestAdditions安装不上，从宿主机到客户机传送文件可用rz/sz。</p>
<p>用ubuntu server硬盘很吃紧，考虑用puppy linux with lamp。如果跑ubuntu server的话，分配64M内存就够用了。</p>
<p>有个问题没解决，宿主机怎么ping通客户机？有没有种方式将ICMP包也转发到客户机上？虽然这样并没有实际的用处。</p>
<p>另可参考felix的解决方案：</p>
<p><a href="http://www.felix021.com/blog/read.php?1873" class="broken_link">用VirtualBox在Windows上搭建一个Ubuntu工作站</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.boluor.com/virtualbox-windows-host-connect-linux-guest.html/feed</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>linux中使用命名管道实现客户端／服务器模型的进程间通信</title>
		<link>http://www.boluor.com/linux-cs-ipc-using-named-pipe.html</link>
		<comments>http://www.boluor.com/linux-cs-ipc-using-named-pipe.html#comments</comments>
		<pubDate>Sun, 16 Aug 2009 11:11:46 +0000</pubDate>
		<dc:creator>boluor</dc:creator>
				<category><![CDATA[程序设计]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[linux]]></category>

		<guid isPermaLink="false">http://www.boluor.com/?p=272</guid>
		<description><![CDATA[<p>　　Linux下进程间通信主要有管道，消息队列，信号量，共享内存，套接口。这里主要说命名管道的一个应用：使用命名管道实现进程间Server/Client机制的通信.</p>
<p>　　之所以去接触它，是因为实验室的项目中要求可信组和加密组可以进行通信。两者都在用户层，加密组向可信组发送请求，可信组返回响应。比如加密小组发送请求密钥信息，可信组返回所请求的密钥。由于传输的信息相对来说比较大,而且这两个程序逻辑上并不相关，所以在几种通信方式中我们选择了命名管道。</p>
<p>　　命名管道其实是FIFO文件。在linux中终端下创建一个管道,用mkfifo命令：mkfifo fifoname；或者mknod命令：mknod fifo&#8230;</p>]]></description>
			<content:encoded><![CDATA[<p>　　Linux下进程间通信主要有管道，消息队列，信号量，共享内存，套接口。这里主要说命名管道的一个应用：使用命名管道实现进程间Server/Client机制的通信.</p>
<p>　　之所以去接触它，是因为实验室的项目中要求可信组和加密组可以进行通信。两者都在用户层，加密组向可信组发送请求，可信组返回响应。比如加密小组发送请求密钥信息，可信组返回所请求的密钥。由于传输的信息相对来说比较大,而且这两个程序逻辑上并不相关，所以在几种通信方式中我们选择了命名管道。</p>
<p>　　命名管道其实是FIFO文件。在linux中终端下创建一个管道,用mkfifo命令：mkfifo fifoname；或者mknod命令：mknod fifoname p；最后的p表明该文件是个管道文件。<br />
<span id="more-272"></span></p>
<p>　　再说下访问FIFO文件。首先利用mkfifo命令创建一个管道文件：mkfifo /tmp/tmpfifo。然后读取其内容：cat /tmp/tmpfifo。可以发现这条命令没有结束，这是因为管道正在等待数据的写入。打开另一个终端，向管道写数据：echo “test” > /tmp/tmpfifo；此时两条命令都正常结束。读取端将打印出从管道中读取到的”test”。当然也可以将一端命令放在后台执行，比如读取时可以用：cat /tmp/tmpfifo &#038; ；(有关这方面的信息，可以查下几条命令：管理作业jobs，将任务放入后台bg，将程序放入前台fg，结束任务kill)。	上面的例子说明了，管道的一方(读取端或者写入端)在未得道另一方时，是一直被阻塞的，当然要想不被阻塞可以通过一些参数设定。在程序中，我们用open函数来打开管道。open函数的第一个参数即为管道文件路径，第二个参数为标志位。标志位有O_RDONLY，O_WRONLY，O_NONBLOCK，前两个参数可以和O_NONBLOCK配合使用，不过会改变open调用的处理方式。它们的作用从名字可以猜出来，O_RDONLY表明作为读取端，O_WRONLY表明作为写入端，O_NONBLOCK表示读取时不阻塞，也就是说这端立即检查管道中有没有数据，不论有没有都会立即返回，不会在没有数据时被阻塞。</p>
<p>　　现在来看如何利用FIFO实现进程间服务器/客户端的通信模式。首先，假设一个很简单的需求：客户端发送一串字符串，服务器将字符串翻转后返送给客户端。因为可能有不同的客户端同时发出请求，我们在回送管道名字中加入客户端进程的pid来标识。</p>
<p>　　首先，我们设计客户端和服务器端通信数据的结构和一些都会用到的系统头文件common.h。</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:Courier new,verdana;"><span style="color: #339933;">#include &quot;unistd.h&quot;</span>
<span style="color: #339933;">#include &quot;stdlib.h&quot;</span>
<span style="color: #339933;">#include &quot;stdio.h&quot;</span>
<span style="color: #339933;">#include &quot;string.h&quot;</span>
<span style="color: #339933;">#include &quot;fcntl.h&quot;</span>
<span style="color: #339933;">#include &quot;limits.h&quot;</span>
<span style="color: #339933;">#include &lt;sys/types.h&gt; </span>
<span style="color: #339933;">#include &lt;sys/stat.h&gt;</span>
<span style="color: #339933;">#include &quot;ctype.h&quot;</span>
<span style="color: #339933;">#define Server_FIFO_Name &quot;serv_fifo&quot;</span>
<span style="color: #339933;">#define Client_FIFO_Name &quot;client_%d_fifo&quot;</span>
&nbsp;
<span style="color: #339933;">#define BufSize 200</span>
&nbsp;
<span style="color: #993333;">struct</span> data_to_pass<span style="color: #009900;">&#123;</span>
	pid_t client_pid<span style="color: #339933;">;</span>	<span style="color: #666666; font-style: italic;">//保存客户端进程的PID。</span>
	<span style="color: #993333;">char</span> str<span style="color: #009900;">&#91;</span>BufSize<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span></pre></div></div>

<p>　　再来看服务器端。服务器端首先要建立管道以便其他进程向其发送数据，然后再打开回送管道，向客户端返回数据，然后再回到开始等待客户端向其请求数据。</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:Courier new,verdana;"><span style="color: #339933;">#include &quot;common.h&quot;</span>
<span style="color: #666666; font-style: italic;">//字符串翻转函数</span>
<span style="color: #993333;">void</span> reverse<span style="color: #009900;">&#40;</span><span style="color: #993333;">char</span> str<span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
	<span style="color: #993333;">int</span> len <span style="color: #339933;">=</span> strlen <span style="color: #009900;">&#40;</span>str<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #993333;">char</span> tmpc<span style="color: #339933;">;</span>
	<span style="color: #993333;">char</span> <span style="color: #339933;">*</span>h<span style="color: #339933;">,*</span>t<span style="color: #339933;">;</span>	
	h <span style="color: #339933;">=</span> str<span style="color: #339933;">;</span> t <span style="color: #339933;">=</span> str <span style="color: #339933;">+</span> <span style="color: #009900;">&#40;</span>len<span style="color: #339933;">-</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #b1b100;">while</span><span style="color: #009900;">&#40;</span>h <span style="color: #339933;">&lt;</span> t<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>	<span style="color: #666666; font-style: italic;">//注意这里不能写成(h != t)</span>
		tmpc <span style="color: #339933;">=</span> <span style="color: #339933;">*</span>h<span style="color: #339933;">;</span>
		<span style="color: #339933;">*</span>h <span style="color: #339933;">=</span> <span style="color: #339933;">*</span>t<span style="color: #339933;">;</span>
		<span style="color: #339933;">*</span>t <span style="color: #339933;">=</span> tmpc<span style="color: #339933;">;</span>
&nbsp;
		h<span style="color: #339933;">++;</span>
		t<span style="color: #339933;">--;</span>
	<span style="color: #009900;">&#125;</span>	
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #993333;">int</span> main<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
	<span style="color: #993333;">int</span> server_fifo_fd<span style="color: #339933;">,</span>client_fifo_fd<span style="color: #339933;">;</span>
	<span style="color: #993333;">struct</span> data_to_pass my_data<span style="color: #339933;">;</span>
	<span style="color: #993333;">int</span> read_res<span style="color: #339933;">;</span>
	<span style="color: #993333;">char</span> client_fifo<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">256</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
	<span style="color: #993333;">char</span> <span style="color: #339933;">*</span>char_ptr<span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">//创建server管道。</span>
	mkfifo<span style="color: #009900;">&#40;</span>Server_FIFO_Name<span style="color: #339933;">,</span><span style="color: #208080;">0777</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
Again<span style="color: #339933;">:</span> 	<span style="color: #666666; font-style: italic;">//偷懒了，用goto去实现循环监听请求.</span>
	<span style="color: #666666; font-style: italic;">//打开服务器端口，等待读取。此时如果客户端还未写入数据服务器端会被阻塞。</span>
	server_fifo_fd <span style="color: #339933;">=</span> open<span style="color: #009900;">&#40;</span>Server_FIFO_Name <span style="color: #339933;">,</span> O_RDONLY<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span> <span style="color: #339933;">-</span><span style="color: #0000dd;">1</span> <span style="color: #339933;">==</span> server_fifo_fd <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
		fprintf<span style="color: #009900;">&#40;</span> stderr <span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;Server fifo failure<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		exit<span style="color: #009900;">&#40;</span>EXIT_FAILURE<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
	<span style="color: #666666; font-style: italic;">//从管道中读取数据。	</span>
	read_res <span style="color: #339933;">=</span> read <span style="color: #009900;">&#40;</span> server_fifo_fd <span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>my_data <span style="color: #339933;">,</span> <span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span>my_data<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>read_res <span style="color: #339933;">&gt;</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
		<span style="color: #666666; font-style: italic;">//将字符串翻转.	</span>
		reverse <span style="color: #009900;">&#40;</span> my_data.<span style="color: #202020;">str</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>	
		<span style="color: #666666; font-style: italic;">//将客户端的pid号加入回送管道文件名中.	</span>
		sprintf <span style="color: #009900;">&#40;</span> client_fifo<span style="color: #339933;">,</span> Client_FIFO_Name <span style="color: #339933;">,</span> my_data.<span style="color: #202020;">client_pid</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #666666; font-style: italic;">//打开回送管道。	</span>
		client_fifo_fd <span style="color: #339933;">=</span> open <span style="color: #009900;">&#40;</span> client_fifo <span style="color: #339933;">,</span> O_WRONLY <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>	
		<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span> <span style="color: #339933;">-</span><span style="color: #0000dd;">1</span> <span style="color: #339933;">!=</span> client_fifo_fd <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
			<span style="color: #666666; font-style: italic;">//向管道中写入返回的数据.</span>
			write <span style="color: #009900;">&#40;</span> client_fifo_fd <span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>my_data<span style="color: #339933;">,</span> <span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span>my_data<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>	
			close <span style="color: #009900;">&#40;</span> client_fifo_fd <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
	<span style="color: #009900;">&#125;</span>	
	close<span style="color: #009900;">&#40;</span>server_fifo_fd<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>	
&nbsp;
	<span style="color: #b1b100;">goto</span> Again<span style="color: #339933;">;</span>	
	unlink<span style="color: #009900;">&#40;</span>Server_FIFO_Name<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	exit<span style="color: #009900;">&#40;</span>EXIT_SUCCESS<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>　　最后就是客户端，模式其实差不多。先打开服务器管道，发送数据，然后创建回送管道，等待服务器返回数据。</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:Courier new,verdana;"><span style="color: #339933;">#include &quot;common.h&quot;</span>
&nbsp;
<span style="color: #993333;">int</span> main<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
	<span style="color: #993333;">int</span> server_fifo_fd<span style="color: #339933;">,</span>client_fifo_fd<span style="color: #339933;">;</span>
	<span style="color: #993333;">struct</span> data_to_pass mydata<span style="color: #339933;">;</span>
	<span style="color: #993333;">int</span> times_to_send<span style="color: #339933;">;</span>
	<span style="color: #993333;">char</span> client_fifo<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">256</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
	<span style="color: #993333;">int</span> rst<span style="color: #339933;">;</span>	
&nbsp;
	<span style="color: #666666; font-style: italic;">//打开服务器管道，开始写入.	采用NON_BLOCK方式，所以需要服务器先打开。</span>
	server_fifo_fd <span style="color: #339933;">=</span> open<span style="color: #009900;">&#40;</span>Server_FIFO_Name<span style="color: #339933;">,</span>O_WRONLY <span style="color: #339933;">|</span> NON_BLOCK<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>server_fifo_fd <span style="color: #339933;">==</span> <span style="color: #339933;">-</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
		fprintf<span style="color: #009900;">&#40;</span>stderr <span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;Sorry ,No Server<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		exit<span style="color: #009900;">&#40;</span>EXIT_FAILURE<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
	<span style="color: #666666; font-style: italic;">//获得当前进程PID存入结构中。	</span>
	mydata.<span style="color: #202020;">client_pid</span> <span style="color: #339933;">=</span> getpid<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	sprintf <span style="color: #009900;">&#40;</span> client_fifo<span style="color: #339933;">,</span>Client_FIFO_Name <span style="color: #339933;">,</span>mydata.<span style="color: #202020;">client_pid</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>mkfifo<span style="color: #009900;">&#40;</span>client_fifo <span style="color: #339933;">,</span><span style="color: #208080;">0777</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #339933;">-</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
		fprintf<span style="color: #009900;">&#40;</span>stderr <span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;Sorry ,can't make %s <span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span>client_fifo<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		exit<span style="color: #009900;">&#40;</span>EXIT_FAILURE<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
	<span style="color: #666666; font-style: italic;">//填写发送的数据包.</span>
	sprintf<span style="color: #009900;">&#40;</span>mydata.<span style="color: #202020;">str</span><span style="color: #339933;">,</span><span style="color: #ff0000;">&quot;%s&quot;</span><span style="color: #339933;">,</span><span style="color: #ff0000;">&quot;12345&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>		
&nbsp;
	<span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;%d sent %s,&quot;</span><span style="color: #339933;">,</span>mydata.<span style="color: #202020;">client_pid</span> <span style="color: #339933;">,</span> mydata.<span style="color: #202020;">str</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #666666; font-style: italic;">//向管道中写入数据：发送.</span>
	write<span style="color: #009900;">&#40;</span>server_fifo_fd <span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>mydata <span style="color: #339933;">,</span> <span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span>mydata<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">//打开回送管道，等待接受从服务器返回的数据。	</span>
	client_fifo_fd <span style="color: #339933;">=</span> open<span style="color: #009900;">&#40;</span>client_fifo<span style="color: #339933;">,</span>O_RDONLY<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>client_fifo_fd <span style="color: #339933;">!=</span> <span style="color: #339933;">-</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>	
		rst <span style="color: #339933;">=</span> read<span style="color: #009900;">&#40;</span> client_fifo_fd <span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>mydata <span style="color: #339933;">,</span> <span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span>mydata<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>			
		<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span> rst <span style="color: #339933;">&gt;</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
			<span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;received : %s<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span>mydata.<span style="color: #202020;">str</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
		close<span style="color: #009900;">&#40;</span>client_fifo_fd<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
	close<span style="color: #009900;">&#40;</span>server_fifo_fd<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	unlink<span style="color: #009900;">&#40;</span>client_fifo<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	exit<span style="color: #009900;">&#40;</span>EXIT_SUCCESS<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>　　至此，一个虽然简单但是比较完整的客户端服务器模式的进程间通信过程完成了。下面是在我机器上的运行效果。</p>
<blockquote><p>
boluor@boluor-laptop:~/programs/pipe/testpipe$ ./server &#038;<br />
[1] 30259<br />
boluor@boluor-laptop:~/programs/pipe/testpipe$ ./client<br />
30301 sent 12345,received : 54321<br />
boluor@boluor-laptop:~/programs/pipe/testpipe$ jobs<br />
[1]+  Running                 ./server &#038;<br />
boluor@boluor-laptop:~/programs/pipe/testpipe$ kill %1
</p></blockquote>
<p>　　至于和socket的比较，首先命名管道是面向连接的，而socket是无连接的；其次，他们都可以实现任意两个进程间的通信；再次，命名管道只是单向传输，要想实现双向必须另建立管道模拟实现。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.boluor.com/linux-cs-ipc-using-named-pipe.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>linux中fork小结</title>
		<link>http://www.boluor.com/summary-of-fork-in-linux.html</link>
		<comments>http://www.boluor.com/summary-of-fork-in-linux.html#comments</comments>
		<pubDate>Mon, 03 Aug 2009 16:05:16 +0000</pubDate>
		<dc:creator>boluor</dc:creator>
				<category><![CDATA[程序设计]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[linux]]></category>

		<guid isPermaLink="false">http://www.boluor.com/?p=223</guid>
		<description><![CDATA[<p>	fork函数在linux中非常重要,因为进程大多是通过它来创建的,比如linux系统在启动时首先创建了进程0,之后的很多进程借助do_fork得到创建.这两天在看匿名管道时了解了下fork,其应用毕竟广,这里只说些我才学到的吧.<br />
	首先来看例1.</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:Courier new,verdana;"><span style="color: #339933;">#include &#34;stdio.h&#34; </span>
<span style="color: #339933;">#include &#34;unistd.h&#34; </span>
<span style="color: #339933;">#include &#34;stdlib.h&#34; </span>
&#160;
<span style="color: #993333;">int</span> main<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span> 
    <span style="color: #993333;">int</span> i<span style="color: #339933;">;</span> 
    <span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&#34;hello world %d<span style="color: #000099; font-weight: bold;">\n</span>&#34;</span><span style="color: #339933;">,</span>getpid<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
    i<span style="color: #339933;">=</span></pre></div></div><p>&#8230;</p>]]></description>
			<content:encoded><![CDATA[<p>	fork函数在linux中非常重要,因为进程大多是通过它来创建的,比如linux系统在启动时首先创建了进程0,之后的很多进程借助do_fork得到创建.这两天在看匿名管道时了解了下fork,其应用毕竟广,这里只说些我才学到的吧.<br />
	首先来看例1.</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:Courier new,verdana;"><span style="color: #339933;">#include &quot;stdio.h&quot; </span>
<span style="color: #339933;">#include &quot;unistd.h&quot; </span>
<span style="color: #339933;">#include &quot;stdlib.h&quot; </span>
&nbsp;
<span style="color: #993333;">int</span> main<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span> 
    <span style="color: #993333;">int</span> i<span style="color: #339933;">;</span> 
    <span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;hello world %d<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span>getpid<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
    i<span style="color: #339933;">=</span><span style="color: #0000dd;">3</span><span style="color: #339933;">;</span> 
    fork<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
    <span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;var %d in  %d<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span>i<span style="color: #339933;">,</span>getpid<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
    <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span> 
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>	输出是什么呢?<br />
	这是在我的机器上一次执行的结果:</p>
<blockquote><p>
hello world 8168<br />
var 3 in  8169<br />
var 3 in  8168
</p></blockquote>
<p>	为什么会有两次输出var 3 一行呢?看似不可思议吧&#8230;要解释原因,就牵涉到了我们要讨论的fork,它到底做了什么?<br />
<span id="more-223"></span><br />
	fork英文是叉的意思.在这里的意思是进程从这里开始分叉,分成了两个进程,一个是父进程,一个子进程.子进程拷贝了父进程的绝大部分.栈阿,缓冲区阿等等.系统为子进程创建一个新的进程表项,其中进程id与父进程是不相同的,这也就是说父子进程是两个独立的进程,虽然父子进程共享代码空间.但是在牵涉到写数据时子进程有自己的数据空间,这是因为copy on write机制,在有数据修改时,系统会为子进程申请新的页面.</p>
<p>	再来复习下进程的有关知识.系统通过进程控制块PCB来管理进程.进程的执行,可以看作是在它的上下文中执行.一个进程的上下文(context)由三部分组成：用户级上下文,寄存器上下文和系统级上下文.用户级上下文中有正文,数据,用户栈和共享存储区;寄存器上下文中有个非常重要的程序计数器(传说中的)PC,还有栈指针和通用寄存器等;系统级上下文分静态和动态,PCB中进程表项,U区,还有本进程的表项,页表,系统区表项等都属于静态部分,而核心栈等则属于动态部分.</p>
<p>	回到fork上来.fork在内核中对应的是do_fork函数,本来想自己写下函数说明的,发现已经有了.详见：<a href="http://blog.sina.com.cn/s/blog_4b9216f50100cwwu.html###">内核 do_fork 函数源代码浅析</a>	. 上面已经提到,fork后,子进程拷贝了父进程的进程表项,还有栈阿,缓冲区,U区等等.当然在这之前会去检查系统有没有可用的资源,取一个空闲的进程表项和唯一的PID号等工作.(后面的例子会体现子进程到底拷贝了父进程的哪些东西.)需要指出的是,这里所说的拷贝,并不是说子进程再申请页面,将父进程中的全部拷贝过来.而是,他们共享一个空间,子进程只是作一层映射而已,这个时候进程页面标记为只读.在有数据修改时,才会申请新的页面,拷贝过来,并标记为可写.</p>
<p>	fork执行后,对父进程和子进程不同的地方还有,对父进程返回子进程的pid号,对子进程返回的是0.大致的算法描述为:</p>
<blockquote><p>
if (当前正在执行的是父进程){<br />
	将子进程的状态设置为”就绪状态”;<br />
	return (子进程的pid号);<br />
}else{	/*正在执行的是子进程*/<br />
	初始化U区等工作;<br />
	return 0;<br />
}
</p></blockquote>
<p>	现在来看例1,是不是已经清晰了很多? 在执行了fork之后,父子进程分别都执行了下一步printf语句.由于fork拷贝走了pc,所以在子进程中不会再从main入口重新执行,而是执行fork后的下一条指令.而i是保存在进程栈空间中的,所以子进程中也存在.<br />
	有了前面的基础,再看下面一个例2:</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:Courier new,verdana;"><span style="color: #339933;">#include &lt;stdio.h&gt;</span>
<span style="color: #339933;">#include &lt;unistd.h&gt;</span>
<span style="color: #993333;">int</span> main<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">int</span> i<span style="color: #339933;">=</span><span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
    pid_t fork_result<span style="color: #339933;">;</span>
    <span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;pid : %d --&gt; main begin()<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span>getpid<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    fork_result <span style="color: #339933;">=</span> fork<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>fork_result <span style="color: #339933;">&lt;</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;Fork Failure<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #b1b100;">for</span><span style="color: #009900;">&#40;</span>i<span style="color: #339933;">=</span><span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>i<span style="color: #339933;">&lt;</span><span style="color: #0000dd;">3</span><span style="color: #339933;">;</span>i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>fork_result <span style="color: #339933;">==</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>   <span style="color: #666666; font-style: italic;">//在子进程中.</span>
            <span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;child process : %d<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span>i<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span><span style="color: #b1b100;">else</span><span style="color: #009900;">&#123;</span>
            <span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;Father process : %d<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span>i<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>	这次输出可以更明确的显示出子进程到底拷贝了些什么.我机器上的两次执行结果:</p>
<blockquote><p>
boluor@boluor-laptop:~/programs/pipe/fork$ ./a.out<br />
pid : 16567 &#8211;> main begin()<br />
child process : 0<br />
child process : 1<br />
child process : 2<br />
Father process : 0<br />
Father process : 1<br />
Father process : 2<br />
boluor@boluor-laptop:~/programs/pipe/fork$ ./a.out<br />
pid : 16569 &#8211;> main begin()<br />
Father process : 0<br />
Father process : 1<br />
Father process : 2<br />
child process : 0<br />
child process : 1<br />
child process : 2
</p></blockquote>
<p>	同时也可以说明,父子进程到底哪个先执行,是跟cpu调度有关系的.如果想固定顺序,那么就要用wait或vfork函数.<br />
	继续看例3：</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:Courier new,verdana;"><span style="color: #339933;">#include &quot;stdio.h&quot;</span>
<span style="color: #339933;">#include &quot;unistd.h&quot;</span>
<span style="color: #339933;">#include &quot;stdlib.h&quot;</span>
&nbsp;
<span style="color: #993333;">int</span> main<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;hello world %d&quot;</span><span style="color: #339933;">,</span>getpid<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #666666; font-style: italic;">//fflush(0);</span>
    fork<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>	执行上面的程序,可以发现输出了两遍hello world.而且两次的pid号都是一样的.这是为什么呢? 这其实是因为printf的行缓冲的问题,printf语句执行后,系统将字符串放在了缓冲区内,并没有输出到stdout.不明白的话看下面的例子:</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:Courier new,verdana;"><span style="color: #339933;">#include &quot;stdio.h&quot;</span>
<span style="color: #993333;">int</span> main<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
	<span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;hello world&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #b1b100;">while</span><span style="color: #009900;">&#40;</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>	执行上面的程序你会发现,程序陷入死循环,并没有输出”hello world”.这就是因为把”hello world”放入了缓冲区.我们平常加&#8217;\n&#8217;的话,就会刷新缓冲区,那样就会直接输出到stdout了.</p>
<p>	因为子进程将这些缓冲也拷贝走了,所以子进程也打印了一遍.父进程直到最后才输出.他们的输出是一样的,输出的pid是一致的,因为子进程拷贝走的是printf语句执行后的结果.如果利用setbuf设置下,或者在printf语句后调用fflush(0);强制刷新缓冲区,就不会有这个问题了.这个例子从侧面显示出子进程也拷贝了父进程的缓冲区.</p>
<p>	关于fork的应用还很多很多,在实际项目中需要了再去深入研究.关于fork和exec的区别,exec是将本进程的映像给替换掉了,跟fork差别还是很大的,其实fork创建子进程后,大部分情况下,子进程会调用exec去执行不同的程序的.</p>
<p>	先说到这里了.如果需要更多fork的知识就google一下^.^.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.boluor.com/summary-of-fork-in-linux.html/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>linux内核模块之间通信</title>
		<link>http://www.boluor.com/communication-between-the-kernel-module-of-linux.html</link>
		<comments>http://www.boluor.com/communication-between-the-kernel-module-of-linux.html#comments</comments>
		<pubDate>Wed, 29 Jul 2009 18:11:42 +0000</pubDate>
		<dc:creator>boluor</dc:creator>
				<category><![CDATA[程序设计]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[linux kernel]]></category>

		<guid isPermaLink="false">http://www.boluor.com/?p=217</guid>
		<description><![CDATA[<p>    今天师兄问，linux内核模块之间如何进行通信？我才想起我之前也有这个疑问，只是当时不需要所以就没去关心了。晚上查了些资料，终于弄明白了些。<br />
    这里的通信可以简单点理解，就是模块B如何调用A的函数，变量或者常量。为了简化，我设计一个模块A中的一个函数为printMSG，原型为int printMSG(int n);传入的参数n表示打印几遍一个固定的字符串。模块A(在helloworld基础上修改的，所以名字都没变&#8230;懒)源码：</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:Courier new,verdana;"><span style="color: #339933;">#include &#60;linux/init.h&#62; </span>
<span style="color: #339933;">#include &#60;linux/module.h&#62;  </span>
<span style="color: #993333;">int</span> __init hello_init<span style="color: #009900;">&#40;</span><span style="color: #993333;">vo</span></pre></div></div><p>&#8230;</p>]]></description>
			<content:encoded><![CDATA[<p>    今天师兄问，linux内核模块之间如何进行通信？我才想起我之前也有这个疑问，只是当时不需要所以就没去关心了。晚上查了些资料，终于弄明白了些。<br />
    这里的通信可以简单点理解，就是模块B如何调用A的函数，变量或者常量。为了简化，我设计一个模块A中的一个函数为printMSG，原型为int printMSG(int n);传入的参数n表示打印几遍一个固定的字符串。模块A(在helloworld基础上修改的，所以名字都没变&#8230;懒)源码：</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:Courier new,verdana;"><span style="color: #339933;">#include &lt;linux/init.h&gt; </span>
<span style="color: #339933;">#include &lt;linux/module.h&gt;  </span>
<span style="color: #993333;">int</span> __init hello_init<span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span> 
    printk<span style="color: #009900;">&#40;</span>KERN_ALERT <span style="color: #ff0000;">&quot;hello world
&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
    <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span> 
<span style="color: #009900;">&#125;</span> 
&nbsp;
<span style="color: #993333;">int</span> printMSG<span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span> n<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span> 
    <span style="color: #993333;">int</span> i<span style="color: #339933;">;</span> 
    <span style="color: #b1b100;">for</span><span style="color: #009900;">&#40;</span>i<span style="color: #339933;">=</span><span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>i<span style="color: #339933;">&lt;</span>n<span style="color: #339933;">;</span>i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> 
        printk<span style="color: #009900;">&#40;</span>KERN_ALERT <span style="color: #ff0000;">&quot;I am boluor
&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
    <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span> 
<span style="color: #009900;">&#125;</span> 
&nbsp;
<span style="color: #993333;">void</span> __exit hello_exit<span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span> 
    printk<span style="color: #009900;">&#40;</span>KERN_ALERT <span style="color: #ff0000;">&quot;byebye,hello world
&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
<span style="color: #009900;">&#125;</span> 
EXPORT_SYMBOL<span style="color: #009900;">&#40;</span>printMSG<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
module_init<span style="color: #009900;">&#40;</span>hello_init<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
module_exit<span style="color: #009900;">&#40;</span>hello_exit<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p><span id="more-217"></span><br />
    其中用到了EXPORT_SYMBOL宏来表明导出printMSG这个符号。还有一个EXPORT_SYMBOL_GPL宏，导出的符号具有GPL授权。内核所有的导出符号可以通过 : cat /proc/kallsyms来查看，太多了，所以最好导出到一个文件中慢慢看。在其中就可以发现printk等等我们常见的内核函数。</p>
<p>    现在我们写一个测试模块B，他将调用A中的printMSG函数。B的源码和A大致一样，这里只给出不同的地方吧。</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:Courier new,verdana;"><span style="color: #000000; font-weight: bold;">extern</span> <span style="color: #993333;">int</span> printMSG<span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span> n<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>  <span style="color: #666666; font-style: italic;">//声明printMSG来自外部文件.</span>
<span style="color: #993333;">int</span> __init test_init<span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>     <span style="color: #666666; font-style: italic;">//在模块加载的时候调用.</span>
    printk<span style="color: #009900;">&#40;</span>KERN_ALERT <span style="color: #ff0000;">&quot;hello world
&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    printMSG<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">3</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>    两个模块的Makefile文件参照<a href="http://www.boluor.com/?p=86">Linux设备驱动学习笔记</a>.编译通过后，先insmod 模块A，再insmod B，就可以发现B可以插入了。查看log，通过dmesg | tail -10就可以发现B在加载的时候输出了三行”I am boluor”。<br />
    通过以上的测试，对linux所谓的LKM有了更深的认识。内核其实就是一个大的程序，当我们动态的加载进入一个模块时，他还是内核这个大程序的一部分，所以我们可以像一个工程中那样，将函数导出到内核符号表中，再将需要调用的外部的函数声明为extern关键字，就可以方便的调用了。</p>
<p>     从回来到现在，搜了很多资料，抄来抄去的，都没说明到底怎么作，问题依旧没有答案。在CSDN上看到一帖，也說得这问题，中有人说，需要使用系统调用。。。不知道怎么想的，反正测试没通过。这些还是得靠不断的去试，才会有正确的结果。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.boluor.com/communication-between-the-kernel-module-of-linux.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>一天纪要</title>
		<link>http://www.boluor.com/summary-today.html</link>
		<comments>http://www.boluor.com/summary-today.html#comments</comments>
		<pubDate>Tue, 16 Jun 2009 17:50:00 +0000</pubDate>
		<dc:creator>boluor</dc:creator>
				<category><![CDATA[日记]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[DLL]]></category>
		<category><![CDATA[FS]]></category>
		<category><![CDATA[linux]]></category>

		<guid isPermaLink="false">http://www.boluor.com/?p=135</guid>
		<description><![CDATA[<p>今天搞定了好多事情，感觉相当不错^.^</p>
<p>凌晨和Sandy在601聊天到4点半多，把很多的事情都好好地讨论了下，感觉下一步做什么怎么做清晰了很多。</p>
<p>上午睡过去的&#8230;</p>
<p>下午到实验室和KouPeng师兄，猜想加搜索后，终于发现ecryptfs的源码原来已经集成到了linux的源码包中，不过不知道为什么ecryptfs的官网都不提示下的。单单搜源码就耗了好长的时间。官网提供的utils包只是如何方便的使用ecryptfs的工具包而已。</p>
<p>回来又把windows核心编程中windows内存结构看了下。DLL到底加载到了什么位置搞明白了。我之前的《detours笔记》中写的DLL在一定程度上说也是正确的，&#8230;</p>]]></description>
			<content:encoded><![CDATA[<p>今天搞定了好多事情，感觉相当不错^.^</p>
<p>凌晨和Sandy在601聊天到4点半多，把很多的事情都好好地讨论了下，感觉下一步做什么怎么做清晰了很多。</p>
<p>上午睡过去的&#8230;</p>
<p>下午到实验室和KouPeng师兄，猜想加搜索后，终于发现ecryptfs的源码原来已经集成到了linux的源码包中，不过不知道为什么ecryptfs的官网都不提示下的。单单搜源码就耗了好长的时间。官网提供的utils包只是如何方便的使用ecryptfs的工具包而已。</p>
<p>回来又把windows核心编程中windows内存结构看了下。DLL到底加载到了什么位置搞明白了。我之前的《detours笔记》中写的DLL在一定程度上说也是正确的，那就是在系统分配的用户地址空间为3G的时候。在XP下的boot.ini中启动项加入/3G开关，讲会使用户空间程序的地址空间为3G，内核被压缩到剩下的1G空间中。这样会导致系统能创建线程，堆栈和其它资源数量的减少，此外，系统最多只能使用16GB的RAM，而通常情况下最多可以使用64GB的RAM，因为内存方式中没有足够的虚拟地址空间来管理更多的RAM。XP默认不开3G开关，这种情况下，DLL等加载的地址是在2G一下的。这也就解释了我之前的疑惑，为什么用IceSword看DLL的base地址时，都是0&#215;80000000下的。<br />
<span id="more-135"></span><br />
刚才和Sandy聊天，说到《c缺陷与陷阱》中提到的(*(void(*)())0)()怎么通过剥皮的方式逐步搞清楚他的真面目。比较复杂的式子在c++中也有，也需要花点功夫去搞明白。之后说，c和c++对NULL的定义是不一样的&#8230;我想了想没有想法，只知道c中的定义是 ((void *)0)，c++中对NULL直接定义为0。这样子问题来了，例如在c++中重载时，两个函数:</p>
<p>int test(int a);</p>
<p>int test( char *b);</p>
<p>这种情况下调用test(NULL)本意是传指针但却被当做是一个普通的整数0了。</p>
<p>还有一点，为什么一个程序的返回值如果是BOOL型的时候为什么一般不判断是否为TRUE，而可以判断是否为FALSE，更一般的情况下市判断0或者非0。因为通常情况下，FALSE只有一个值就是0，但是其他所有的都为真。这样如果有个程序可以返回3，4，5等整型值来表示不同的返回信息，用TRUE就很难判断函数是否运行失败。恩，还有函数的返回值如果是PVOID类型的话表示是数据块的内存地址，在API中经常见到。</p>
<p>最觉得有收获的，是Sandy推荐的牛人的文章，也就是pongba的博客。不论是《why c++》还是《为什么你应该（从现在开始就）写博客》，还是《书写是为了更好的思考》，篇篇经典，相当值得收藏。</p>
<p>最后吧，Sandy推荐说没事就看下《c++标准程序库》吧，我确实也应该看了。c++相当的值得学习。另，微软俱乐部的申请写的太简略了，Sandy说别人一看还以为你在BS人家&#8230;真没那意思，本来写的比较多，考虑到怕人家看着烦，才总结成两句话的&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.boluor.com/summary-today.html/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Ubuntu下php使用GD库笔记</title>
		<link>http://www.boluor.com/using-php-gd-library-notes-under-ubuntu.html</link>
		<comments>http://www.boluor.com/using-php-gd-library-notes-under-ubuntu.html#comments</comments>
		<pubDate>Sat, 30 May 2009 02:45:42 +0000</pubDate>
		<dc:creator>boluor</dc:creator>
				<category><![CDATA[程序设计]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://www.boluor.com/?p=99</guid>
		<description><![CDATA[<p>    准备给博客写个验证码的，但是在使用GD库生成图片的时候，问题多多，还好现在算是解决了一些。写点下来方便朋友查阅吧，省得像我一样海搜了两天。</p>
<p>    首先是查看GD库有没有被正确的安装和加载.通过gd_info()可以看，或者phpinfo。在phpinfo中可以看到gd一栏，然后版本如果是bundled (2.0.34 compatible) 的话，是从php4.3之后开始绑定的。如果没有的话，可以用命令安装一个:<br />
sudo apt-get install php5-gd.或者为了安装完整版本的,在源列表中添加两行：<br />
deb http://packages.dotdeb.org stable all<br />
deb-src http:/&#8230;</p>]]></description>
			<content:encoded><![CDATA[<p>    准备给博客写个验证码的，但是在使用GD库生成图片的时候，问题多多，还好现在算是解决了一些。写点下来方便朋友查阅吧，省得像我一样海搜了两天。</p>
<p>    首先是查看GD库有没有被正确的安装和加载.通过gd_info()可以看，或者phpinfo。在phpinfo中可以看到gd一栏，然后版本如果是bundled (2.0.34 compatible) 的话，是从php4.3之后开始绑定的。如果没有的话，可以用命令安装一个:<br />
sudo apt-get install php5-gd.或者为了安装完整版本的,在源列表中添加两行：<br />
deb http://packages.dotdeb.org stable all<br />
deb-src http://packages.dotdeb.org stable all<br />
    然后升级下：sudo apt-get update. 再安装php5-gd.</p>
<p>    网上有说，安装完成后php.ini会更新，但是我的并没有。搜到gd.so在/usr/lib/php5/20060613+lfs/下,php.ini在/etc/php5/apach2下.于是手动修改php.ini。在其中修改extension_dir=”/usr/lib/php5/20060613+lfs/”,再添加一行extension=gd.so.之后重启apach2:  sudo /etc/init.d/apach2 restart。</p>
<p>    这些完成后可以写个测试的小程序。我使用的是php手册上的例子.文件名为pic.php。</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
</pre></td><td class="code"><pre class="php" style="font-family:Courier new,verdana;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
    <span style="color: #990000;">header</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Content-type:image/png&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$im</span><span style="color: #339933;">=</span> <span style="color: #990000;">imagecreatetruecolor</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">300</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">200</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$bg_color</span><span style="color: #339933;">=</span>  <span style="color: #990000;">imagecolorallocate</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$im</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$text_color</span><span style="color: #339933;">=</span> <span style="color: #990000;">imagecolorallocate</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$im</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">23</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">14</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">91</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #990000;">imagestring</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$im</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">5</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">5</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;A Simple Text String&quot;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$text_color</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #990000;">imagepng</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$im</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #990000;">imagedestroy</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$im</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></td></tr></table></div>

<p>     浏览器中打开时，开始遇到了些问题。发现提示我下载文件，下载后用gvim打开发现是乱码，不过其中可以看到PNG字样，猜想这应该就是png图像的二进制数据，不过没有被浏览器识别。用ultraedit和其他的png图像对比后，发现PNG图像头都相同，只是结尾多了四个字节。不过更名为pic.png后可以用图像查看器打开。</p>
<p>     继续搜，最后在phpchina论坛上看到了很多人问这个问题。找到了一个貌似答案的说法。说是这个php代码是生成图片的，所以不要在php代码之前输出任何东西，包括空格。试了下，果然可以了。不过需要先关闭浏览器，再打开，不然浏览器输出的是缓存的东西。在另一个文件test.php中用img的src属性调用src=”pic.php”,这个显示正常。所以我觉得，如果需要用gd库生成图片的，最好生成图片的文件单独出来。</p>
<p>     终于纠结完了，开始写验证码。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.boluor.com/using-php-gd-library-notes-under-ubuntu.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

