<?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.xiangmocheng.com/category/linux/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.xiangmocheng.com</link>
	<description>彪悍的代码不需要注释</description>
	<lastBuildDate>Wed, 30 Nov 2011 11:47:45 +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>Ubuntu上构筑iPhone OS3.1.2开发环境(toolchain)</title>
		<link>http://www.xiangmocheng.com/2010/04/build-iphone-os-3-1-2-development-environment-on-ubuntu/</link>
		<comments>http://www.xiangmocheng.com/2010/04/build-iphone-os-3-1-2-development-environment-on-ubuntu/#comments</comments>
		<pubDate>Mon, 19 Apr 2010 08:57:19 +0000</pubDate>
		<dc:creator>xiangmocheng</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Ubuntu]]></category>

		<guid isPermaLink="false">http://www.xiangmocheng.com/?p=70054</guid>
		<description><![CDATA[在建立编译环境前，请先下载好所需的SDK和Firmware文件： iPhone1,2_3.1.2_7D11_Restore.ipsw iphone_sdk_3.1.2_with_xcode_3.1.4__leopard__9m2809.dmg 我的Linux HOST环境为Ubuntu 9.10（Karmic Koala），在这里利用iphonedevonlinux建立toolchain。 首先配置好编译所需的HOST环境，在终端中输入以下命令： 获取iphonedevonlinux源代码： 目前checkout out的svn版本为83。 拷贝SDK，firmware文件到相应目录： 手动设置密匙，注释掉toolchain.sh中下载密匙的代码： 我们可以利用 自动编译toolchain，但容易出现很多问题。这里我们采用手动一步步编译： 一般来说前三步都不会出现什么问题。（有问题请留言） 最后一步toolchain.sh build中会报错，这时打开～/iphone/toolchain/toolchain/bld/cctools-iphone/make.log，搜索”error:”，在报错的文件中加上： 以下是我修改的文件： ArchiveReader.hpp MachOReaderDylib.hpp MachOWriterExecutable.hpp OpaqueSection.hpp ld.cpp Options.cpp 重新build即可。注意不要重新checkout代码，不然又要重改一遍。。。 如果出现”It seems like the toolchain built!”，说明toolchain build成功。 之后可以利用apps下的代码测试下toolchain，一般会遇到两个问题： 1. 找不到编译器 arm-apple-darwin9-gcc 在～/.bashrc中添加环境变量即可 增加export PATH=～/iphone/toolchain/toolchain/pre/bin:$PATH 2. 提示”ld: library not found for -lobjc” 拷贝以下目录到编译器库中： 参考文章：iphonedevonlinux installation iPhone开发入门（3）—Linux上构筑iPhone OS3.1.2开发环境 转载请注明： 转载自不然你要我怎么样 本文链接地址: [...]]]></description>
			<content:encoded><![CDATA[<p>在建立编译环境前，请先下载好所需的SDK和Firmware文件：</p>
<ul>
<li><a href="http://mytopfiles.com/other/file/iPhone1,2_3-1-2_7D11_Restore/342866.htm">iPhone1,2_3.1.2_7D11_Restore.ipsw</a></li>
<li><a href="http://shuqun.com/files/iphone_sdk_3.1.2_with_xcode_3.1.4__leopard__9m2809.dmg">iphone_sdk_3.1.2_with_xcode_3.1.4__leopard__9m2809.dmg</a></li>
</ul>
<p>我的Linux HOST环境为Ubuntu 9.10（Karmic Koala），在这里利用<a href="http://code.google.com/p/iphonedevonlinux/">iphonedevonlinux</a>建立toolchain。</p>
<p>首先配置好编译所需的HOST环境，在终端中输入以下命令：</p>
<pre class="brush: bash; title: ; notranslate">sudo apt-get install  automake bison cpio flex g++ g++-4.3 g++-4.3-multilib gawk gcc-4.3 git-core gobjc-4.3 gzip libbz2-dev libcurl4-openssl-dev libssl-dev  make mount subversion sudo tar unzip uuid uuid-dev wget xar zlib1g-dev</pre>
<p>获取<a href="http://code.google.com/p/iphonedevonlinux/">iphonedevonlinux</a>源代码：</p>
<pre class="brush: bash; title: ; notranslate">$ mkdir -p ~/iphone/toolchain
$ cd ~/iphone/toolchain
$ svn checkout http://iphonedevonlinux.googlecode.com/svn/trunk/ ./</pre>
<p>目前checkout out的svn版本为83。</p>
<p>拷贝SDK，firmware文件到相应目录：</p>
<pre class="brush: bash; title: ; notranslate">$ mkdir -p ~/iphone/toolchain/files/firmware
$ mv ./iphone_sdk_3.1.2_with_xcode_3.1.4__leopard__9m2809.dmg ~/iphone/toolchain/files/
$ mv ./iPhone1,2_3.1.2_7D11_Restore.ipsw ~/iphone/toolchain/files/firmware/</pre>
<p>手动设置密匙，注释掉toolchain.sh中下载密匙的代码：</p>
<pre class="brush: bash; title: ; notranslate">$ gedit ~/iphone/toolchain/toolchain.sh</pre>
<pre class="brush: bash; title: ; notranslate">unzip -d &quot;${TMP_DIR}&quot; -o &quot;${FW_FILE}&quot; &quot;${FW_RESTORE_SYSTEMDISK}&quot;

＃if [ -z &quot;$DECRYPTION_KEY_SYSTEM&quot; ] ; then
＃echo &quot;We need the decryption key for `basename $FW_RESTORE_SYSTEMDISK`.&quot;
＃echo &quot;I'm going to try to fetch it from $IPHONEWIKI_KEY_URL....&quot;
＃
＃IPHONEWIKI_KEY_URL=$( wget --quiet -O - $IPHONEWIKI_KEY_URL | awk '
＃BEGIN { IGNORECASE = 1; }
＃/name=&quot;'${DEVICE}'/  { found_phone=1; }
＃/.*'${TOOLCHAIN_VERSION}'.*/ &amp;amp;&amp;amp; found_phone { found_firmware=1; }
＃/.*href=.*/ &amp;amp;&amp;amp; found_firmware { while(sub(/href=|&quot;/,&quot;&quot;, $3));; print $3; exit;}
＃')

＃DECRYPTION_KEY_SYSTEM=`wget --quiet -O - &quot;http://www.theiphonewiki.com&quot;$IPHONEWIKI_KEY_URL | awk '
＃BEGIN { IGNORECASE = 1; }
＃/.*VFDecrypt.*/  { print $3;}
＃'`

DECRYPTION_KEY_SYSTEM=&quot;a8a886d56011d2d98b190d0a498f6fcac719467047639cd601fd53a4a1d93c24e1b2ddc6&quot;

if [ ! &quot;$DECRYPTION_KEY_SYSTEM&quot; ] ; then</pre>
<p>我们可以利用</p>
<pre class="brush: bash; title: ; notranslate">$ sudo ./toolchain.sh all</pre>
<p>自动编译toolchain，但容易出现很多问题。这里我们采用手动一步步编译：</p>
<pre class="brush: bash; title: ; notranslate">$ sudo./toolchain.sh headers
$ sudo./toolchain.sh firmware
$ sudo./toolchain.sh darwin_sources
$ sudo./toolchain.sh build</pre>
<p>一般来说前三步都不会出现什么问题。（有问题请留言）</p>
<p>最后一步toolchain.sh build中会报错，这时打开～/iphone/toolchain/toolchain/bld/cctools-iphone/make.log，搜索”error:”，在报错的文件中加上：</p>
<pre class="brush: bash; title: ; notranslate">#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;</pre>
<p>以下是我修改的文件：<br />
ArchiveReader.hpp  MachOReaderDylib.hpp  MachOWriterExecutable.hpp  OpaqueSection.hpp  ld.cpp  Options.cpp</p>
<p>重新build即可。注意不要重新checkout代码，不然又要重改一遍。。。</p>
<p>如果出现”It seems like the toolchain built!”，说明toolchain build成功。</p>
<p>之后可以利用apps下的代码测试下toolchain，一般会遇到两个问题：</p>
<p>1. 找不到编译器 arm-apple-darwin9-gcc</p>
<p>在～/.bashrc中添加环境变量即可</p>
<pre class="brush: bash; title: ; notranslate">$ sudo gedit ～/.bashrc</pre>
<p>增加export PATH=～/iphone/toolchain/toolchain/pre/bin:$PATH</p>
<p>2. 提示”ld: library not found for -lobjc”</p>
<p>拷贝以下目录到编译器库中：</p>
<pre class="brush: bash; title: ; notranslate">mv ~/iphone/toolchain/toolchain/sys/System ~/iphone/toolchain/toolchain/sys/System2
mv ~/iphone/toolchain/toolchain/sys/usr/lib ~/iphone/toolchain/toolchain/sys/usr/lib2
cp ~/iphone/toolchain/sdks/iPhoneOS3.1.2.sdk/System ~/iphone/toolchain/toolchain/sys/
cp ~/iphone/toolchain/sdks/iPhoneOS3.1.2.sdk/usr/lib ~/iphone/toolchain/toolchain/sys/usr/</pre>
<p>参考文章：<a title="iphonedevonlinux installation" href="http://code.google.com/p/iphonedevonlinux/wiki/Installation">iphonedevonlinux  installation</a></p>
<p><a title="iPhone开发入门（3）—Linux上构筑iPhone OS3.1.2开发环境" href="http://www.yifeiyang.net/iphone-development-introduction-3-linux-development-environment-on-the-build-iphone-os3-1-2/">iPhone开发入门（3）—Linux上构筑iPhone OS3.1.2开发环境</a>
<div style="margin-top: 10px">
<p><strong>转载请注明：</strong> 转载自<a href="http://www.xiangmocheng.com/">不然你要我怎么样</a></t>        </br><strong>本文链接地址:</strong> <a href="http://www.xiangmocheng.com/2010/04/build-iphone-os-3-1-2-development-environment-on-ubuntu/">Ubuntu上构筑iPhone OS3.1.2开发环境(toolchain)</a></div>
]]></content:encoded>
			<wfw:commentRss>http://www.xiangmocheng.com/2010/04/build-iphone-os-3-1-2-development-environment-on-ubuntu/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>解决Xmarks不能同步的方法</title>
		<link>http://www.xiangmocheng.com/2010/01/how-to-synchronize-xmarks/</link>
		<comments>http://www.xiangmocheng.com/2010/01/how-to-synchronize-xmarks/#comments</comments>
		<pubDate>Sun, 03 Jan 2010 05:48:10 +0000</pubDate>
		<dc:creator>xiangmocheng</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Xmarks]]></category>

		<guid isPermaLink="false">http://www.xiangmocheng.com/?p=69731</guid>
		<description><![CDATA[1. 修改hosts文件： Ubuntu：#sudo gedit /etc/hosts Windows XP：x:\windows\system32\drivers\etc\hosts 加入下面的IP，保存即可。 #xmarks 64.147.188.86 www.xmarks.com 64.147.188.92 api.xmarks.com 64.147.188.89 login.xmarks.com 64.147.188.87 sync.xmarks.com 64.147.188.86 static.xmarks.com 64.147.188.86 download.xmarks.com 64.147.188.86 my.xmarks.com 如果还不行就在xmarks的设置里选高级，再选择“全部加密”，应该就可以同步了。 2. 如果你有自己的FTP服务器，也可以使用自己的服务器进行同步： 1). 在你的站点空间服务器上新建一个目录，比如/Xmarks。 2). 在Xmarks的Status选项中，用户名和密码改为你自己空间服务器ftp的用户名和密码。 3). 在Xmarks的高级选项中，勾选“使用自己的服务器”，地址中输入你的ftp地址+刚才的目录名+保存的文件名,比如： ftp://xx.xx.xx.xx/Xmarks/xmarks.json password url是密码的保存地址，输入： ftp://xx.xx.xx/Xmarks/passwords.json（我没有使用密码同步，所以不知道此项功能能使否可用）。 4). 回到Status选项，“马上同步”即可。使用时如果询问，选择强制覆盖服务器书签，以后在其他机器第一次使用时候需要强制覆盖本地书签。 转载请注明： 转载自不然你要我怎么样 本文链接地址: 解决Xmarks不能同步的方法]]></description>
			<content:encoded><![CDATA[<p>1. 修改hosts文件：</p>
<p>Ubuntu：#sudo gedit /etc/hosts</p>
<p>Windows XP：x:\windows\system32\drivers\etc\hosts</p>
<p>加入下面的IP，保存即可。</p>
<p>#xmarks<br />
64.147.188.86 www.xmarks.com<br />
64.147.188.92 api.xmarks.com<br />
64.147.188.89 login.xmarks.com<br />
64.147.188.87 sync.xmarks.com<br />
64.147.188.86 static.xmarks.com<br />
64.147.188.86 download.xmarks.com<br />
64.147.188.86 my.xmarks.com</p>
<p>如果还不行就在xmarks的设置里选高级，再选择“全部加密”，应该就可以同步了。</p>
<p>2. 如果你有自己的FTP服务器，也可以使用自己的服务器进行同步：</p>
<p>1). 在你的站点空间服务器上新建一个目录，比如/Xmarks。</p>
<p>2). 在Xmarks的Status选项中，用户名和密码改为你自己空间服务器ftp的用户名和密码。</p>
<p>3). 在Xmarks的高级选项中，勾选“使用自己的服务器”，地址中输入你的ftp地址+刚才的目录名+保存的文件名,比如：</p>
<p>ftp://xx.xx.xx.xx/Xmarks/xmarks.json</p>
<p>password url是密码的保存地址，输入：</p>
<p>ftp://xx.xx.xx/Xmarks/passwords.json（我没有使用密码同步，所以不知道此项功能能使否可用）。</p>
<p>4). 回到Status选项，“马上同步”即可。使用时如果询问，选择强制覆盖服务器书签，以后在其他机器第一次使用时候需要强制覆盖本地书签。
<div style="margin-top: 10px">
<p><strong>转载请注明：</strong> 转载自<a href="http://www.xiangmocheng.com/">不然你要我怎么样</a></t>        </br><strong>本文链接地址:</strong> <a href="http://www.xiangmocheng.com/2010/01/how-to-synchronize-xmarks/">解决Xmarks不能同步的方法</a></div>
]]></content:encoded>
			<wfw:commentRss>http://www.xiangmocheng.com/2010/01/how-to-synchronize-xmarks/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ubuntu下使用svn下载和上传内核源代码</title>
		<link>http://www.xiangmocheng.com/2009/12/how-to-use-svn-on-ubuntu/</link>
		<comments>http://www.xiangmocheng.com/2009/12/how-to-use-svn-on-ubuntu/#comments</comments>
		<pubDate>Mon, 07 Dec 2009 08:31:54 +0000</pubDate>
		<dc:creator>xiangmocheng</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[SVN]]></category>
		<category><![CDATA[Ubuntu]]></category>

		<guid isPermaLink="false">http://xiangmocheng.yo2.cn/articles/ubuntu%e4%b8%8b%e4%bd%bf%e7%94%a8svn%e4%b8%8b%e8%bd%bd%e5%92%8c%e4%b8%8a%e4%bc%a0%e5%86%85%e6%a0%b8%e6%ba%90%e4%bb%a3%e7%a0%81.html</guid>
		<description><![CDATA[(1) 安装svn sudo apt-get install subversion (2) 从库里checkout 最新kernel svn checkout https://10.136.7.4/svn/Android/SW/6410/urbetter/kernel &#8211;username benjamin &#8211;password aa123456 &#8211;no-auth-cache &#8211;non-interactive (3) 查看本地文件状态 svn status (4) 查看本地文件和库里的区别 svn diff FILE_PATH (5) 将修改确认到库里 (建议make distclean之后再上传) svn commit 如果是新增文件,需要先添加 svn add PATH 如果要将本地新文件和改动的文件全部上传至库里,可以使用 svn status &#124; grep “?” &#124; xargs svn add (6) 查看帮助 svn help 转载请注明： 转载自不然你要我怎么样 本文链接地址: Ubuntu下使用svn下载和上传内核源代码]]></description>
			<content:encoded><![CDATA[<p>(1) 安装svn</p>
<p>sudo apt-get install subversion</p>
<p>(2) 从库里checkout 最新kernel</p>
<p>svn checkout <span style="color: #339966;">https://10.136.7.4/svn/Android/SW/6410/urbetter/kernel</span> <span style="color: #0000ff;">&#8211;username benjamin</span> <span style="color: #ff0000;">&#8211;password aa123456</span> &#8211;no-auth-cache &#8211;non-interactive</p>
<p>(3) 查看本地文件状态</p>
<p>svn status</p>
<p>(4) 查看本地文件和库里的区别</p>
<p>svn diff <span style="color: #ff0000;">FILE_PATH</span></p>
<p>(5) 将修改确认到库里 (建议make distclean之后再上传)</p>
<p>svn commit</p>
<p>如果是新增文件,需要先添加</p>
<p>svn add <span style="color: #ff0000;">PATH</span></p>
<p>如果要将本地新文件和改动的文件全部上传至库里,可以使用</p>
<p>svn status | grep “?” | xargs svn add</p>
<p>(6) 查看帮助</p>
<p>svn help
<div style="margin-top: 10px">
<p><strong>转载请注明：</strong> 转载自<a href="http://www.xiangmocheng.com/">不然你要我怎么样</a></t>        </br><strong>本文链接地址:</strong> <a href="http://www.xiangmocheng.com/2009/12/how-to-use-svn-on-ubuntu/">Ubuntu下使用svn下载和上传内核源代码</a></div>
]]></content:encoded>
			<wfw:commentRss>http://www.xiangmocheng.com/2009/12/how-to-use-svn-on-ubuntu/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ubuntu常用设置</title>
		<link>http://www.xiangmocheng.com/2009/12/ubuntu-setting/</link>
		<comments>http://www.xiangmocheng.com/2009/12/ubuntu-setting/#comments</comments>
		<pubDate>Fri, 04 Dec 2009 09:15:54 +0000</pubDate>
		<dc:creator>xiangmocheng</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Ubuntu]]></category>

		<guid isPermaLink="false">http://xiangmocheng.yo2.cn/articles/ubuntu%e5%b8%b8%e7%94%a8%e8%ae%be%e7%bd%ae.html</guid>
		<description><![CDATA[﻿1. 为Firefox添加下载工具 MultiGet 安装下载工具 MultiGet $ sudo apt-get install multiget 集成下载工具到FireFox里，使用FlashGot插件, 点击这里下载flashgot最新版，直接拖进FireFox浏览器里即可加载。 FlashGot插件的设置 (1). 打开Flashgot选项，点击“常规”标签页。 (2). 因为下载管理器里面是没有Multiget的，所以点击“新增”，填入Multiget。 (3). 选择程序/usr/bin/multiget (4). 在参数模板中填写： [url=URL] [refer=REFERER] 注意，字符是半角的，两个元素之间有一个空格。 (5).勾上添加到邮件菜单 2. 输入法 下载scim-pinyin包并进行安装。 然后用im-switch -c设定默认的语言引擎,或者在系统-&#62;首选项-&#62;SCIM输入法设置里修改。 安装完要重启(或者logout)。 9.04中用ibus替换scim： (1). 删除scim $ sudo apt-get remove scim &#38;&#38; sudo apt-get autoremove 如果删除了中文支持就再装一遍 sudo apt-get install language-support-fonts-zh (2). 加入ibus的PPA源 ibus1.1.0: $ echo &#8216;deb http://ppa.launchpad.net/ibus-dev/ppa/ubuntu [...]]]></description>
			<content:encoded><![CDATA[<p>﻿1. 为Firefox添加下载工具 MultiGet</p>
<p>安装下载工具 MultiGet</p>
<p>$ sudo apt-get install multiget</p>
<p>集成下载工具到FireFox里，使用FlashGot插件, 点击<a title="flashgot-1.2.1.18.xpi" href="https://secure.informaction.com/download/releases/flashgot-1.2.1.18.xpi">这里</a>下载flashgot最新版，直接拖进FireFox浏览器里即可加载。</p>
<p>FlashGot插件的设置</p>
<p>(1). 打开Flashgot选项，点击“常规”标签页。</p>
<p>(2). 因为下载管理器里面是没有Multiget的，所以点击“新增”，填入Multiget。</p>
<p>(3). 选择程序/usr/bin/multiget</p>
<p>(4). 在参数模板中填写：</p>
<p>[url=URL] [refer=REFERER]</p>
<p>注意，字符是半角的，两个元素之间有一个空格。<br />
(5).勾上添加到邮件菜单</p>
<p>2. 输入法</p>
<p><span style="text-decoration: line-through;">下载scim-pinyin包并进行安装。</span></p>
<p><span style="text-decoration: line-through;">然后用im-switch -c设定默认的语言引擎,或者在系统-&gt;首选项-&gt;SCIM输入法设置里修改。</span></p>
<p><span style="text-decoration: line-through;">安装完要重启(或者logout)。</span></p>
<p>9.04中用ibus替换scim：</p>
<p>(1). 删除scim</p>
<p>$ sudo apt-get remove scim &amp;&amp; sudo apt-get autoremove</p>
<p>如果删除了中文支持就再装一遍</p>
<p>sudo apt-get install language-support-fonts-zh</p>
<p>(2). 加入ibus的PPA源</p>
<p>ibus1.1.0:</p>
<p>$ echo &#8216;deb http://ppa.launchpad.net/ibus-dev/ppa/ubuntu jaunty main&#8217; &gt;&gt; /etc/apt/sources.list</p>
<p>ibus1.2.0 for 9.04:</p>
<p>$ echo &#8216;deb http://ppa.launchpad.net/ibus-dev/ibus-1.2-jaunty/ubuntu jaunty main&#8217; &gt;&gt; /etc/apt/sources.list</p>
<p>$ sudo apt-get update</p>
<p>如果出现签名验证错误：</p>
<p>W: GPG签名验证错误： http://ppa.launchpad.net intrepid Release: 由于没有公钥，下列签名无法进行验证： NO_PUBKEY 5A9BF3BB9D1A0061</p>
<p>把后八位拷贝一下来，替换掉下面命令中的后八位数字</p>
<p>sudo apt-key adv &#8211;recv-keys &#8211;keyserver keyserver.Ubuntu.com 9D1A0061</p>
<p>(3). 安装ibus</p>
<p>$ sudo apt-get install ibus-gtk ibus-pinyin python-xdg<br />
$ im-switch -s ibus -a default</p>
<p>(4). 如果不能正常使用 iBus，将下面代码加入到 $HOME/.bashrc中，并重新登录桌面。</p>
<p>export IBUS_PREFIX=/usr<br />
export GTK_IM_MODULE=ibus<br />
export XMODIFIERS=@im=ibus<br />
export QT_IM_MODULE=ibus</p>
<p>3. 桌面快捷方式以及图标</p>
<p>可以添加桌面快捷方式,也可以添加面板快捷方式。</p>
<p>系统中的图标文件（包括主题图标）主要在/usr/share/icons/以及~/.icons里。这些图标主要都是svg格式，通过eog可以转换为png、jpg等等常用格式。</p>
<p>4. 让Ubuntu桌面显示回收站：</p>
<p>使用快捷键Alt+F2打开运行窗口。键入gconf-editor，打开Gnome配置编辑器，定位到apps\nautilus\desktop。</p>
<p>在右侧找到名为trash_icon_visible的选项，打上勾。其他的桌面图标类似。</p>
<p><span id="more-69494"></span></p>
<p>5. 如何消除软件安装失败造成的垃圾</p>
<p>运行apt synaptic（新立得软件包管理器），彻底删除已损坏的软件包。</p>
<p>6. Ubuntu的官方包网站</p>
<p>http://packages.ubuntu.com, 注意各个ubuntu发布的版本对应不同的名字,比如8.1对应的是intrepid</p>
<p>7. 访问Windows的共享目录方法</p>
<p>sudo mount //10.136.7.5/”R&amp;D” /mnt/liteon/ -o iocharset=utf8,username=ericwang,password=123456,codepage=cp936,uid=0</p>
<p>8. 设置快捷方式</p>
<p>(1). 打开终端输入 gconf-editor</p>
<p>(2). 打开“Apps-&gt;Metacity-&gt;keybinding Commands”</p>
<p>9. 去掉桌面上的已挂载盘符和加上“计算机”等图标</p>
<p>定位到“/apps/nautilus/desktop”，勾上“Computer_icon_visible”,“Home_icon_visible”“Network_icon_visible”，</p>
<p>这样桌面上就有 “计算机”“主目录”“网络服务器”三个图标了，</p>
<p>再把“Volumes_visible”的勾去掉，这样桌面上的已挂载的图标就会消失，以后需要再进“计算机”里找就OK了！</p>
<p>10. FireFox保存和打开mht文件，只需要安装以下任意一个插件即可</p>
<p>(1). 安装MAF插件</p>
<p>(2). 安装IE Tab插件 安装地址：http://ftp.mozine.cn/addons/extensions/ie_tab/ie_tab-1.5.20080823-fx-windows.xpi</p>
<p>(3). 安装UnMHT插件 http://www.unmht.org/unmht/files/unmht-4.9.3.xpi</p>
<p>11. 设置锁定桌面的快捷键</p>
<p>(1). 打开终端输入 gconf-editor</p>
<p>(2). /apps/gnome_settings_daemon/keybindings/screensaver</p>
<p>12. 设置tftp服务器</p>
<p>(1). 安装包</p>
<p>$ sudo apt-get install tftp-hpa tftpd-hpa</p>
<p>(2). 设置tftpd</p>
<p>$ sudo vim /etc/default/tftpd-hpa</p>
<p>RUN_DAEMON=”yes” #改为yes，表示启动守护进程，tftpd工作<br />
OPTIONS=”-l -s /tftpboot” #改为/tftpboot, 表示tftp客户端能取得的文件所存放的位置</p>
<p>(3). 启动服务(通过这个文件调用in.tftpd)</p>
<p>$ sudo /etc/init.d/tftpd-hpa start</p>
<p>(4). 查看服务是否开始工作</p>
<p>$ sudo netstat -pna|grep tft</p>
<p>(5). 测试, 先拷贝一个文件a.txt到目录/tftpboot,然后连接tftp</p>
<p>$ tftp localhost<br />
tftp&gt; get a.txt<br />
tftp&gt; quit<br />
$ ls</p>
<p>如果仍有问题，卸载后重新安装</p>
<p>$ sudo apt-get remove tftpd-hpa</p>
<p>复位重新启动Ubuntu系统</p>
<p>$ sudo apt-get install tftpd-hpa</p>
<p>再重复上边的设置.</p>
<p>13. 在Ubuntu系统上安装nfs方法:</p>
<p>(1). 安装包</p>
<p>服务器端： $ sudo apt-get install portmap nfs-kernel-server</p>
<p>客户机端： $ sudo apt-get install portmap nfs-common</p>
<p>(2). 配置共享文件</p>
<p>编辑 /etc/exports, 在其中增加要共享的文件</p>
<p>$ sudo vim /etc/exports</p>
<p>配置, 增加下列行</p>
<p>/media/disk/TMP/RM34H_Linux/rootfs_aesop/rootfs/ *(rw,sync,no_root_squash)</p>
<p>其中/media/disk/TMP/RM34H_Linux/rootfs_aesop/rootfs/是要共享的目录, *代表允许所有的网络段访问, (rw,&#8230;)代表读写等权限.</p>
<p>(3). 在服务器端重启服务</p>
<p>$ sudo /etc/init.d/portmap restart<br />
$ sudo /etc/init.d/nfs-kernel-server restart</p>
<p>注: 若仅仅更改了 /etc/exports, 可以运行下列命令更新:</p>
<p>$ sudo exportfs -r</p>
<p>(4). 服务器安装完之后, 可以这样测试:</p>
<p>$ showmount -e</p>
<p>如果出现下列信息说明安装成功:</p>
<p>xiangmocheng@ubuntu:~$ showmount -e<br />
Export list for ubuntu:<br />
/media/disk/TMP/RM34H_Linux/rootfs_aesop/rootfs *</p>
<p>(5). 服务器端挂载测试</p>
<p>在服务器端创建用于挂载的目录, 并改变属性允许所有用户访问:</p>
<p>$ sudo mkdir /mnt/test<br />
$ sudo chmod 777 /mnt/test</p>
<p>服务器端挂载:</p>
<p>$ sudo mount localhost:/media/disk/TMP/RM34H_Linux/rootfs_aesop/rootfs /mnt/test<br />
$ ls /mnt/test<br />
$ umount /mnt/test<br />
$ sudo rm /mnt/test -r</p>
<p>(6). 客户机端挂载</p>
<p>在客户机端创建用于挂载的目录, 并改变属性允许所有用户访问:</p>
<p>$ sudo mkdir /mnt/share<br />
$ sudo chmod 777 /mnt/share</p>
<p>客户机端挂载:</p>
<p>$ sudo mount 10.136.4.7:/media/disk/TMP/RM34H_Linux/rootfs_aesop/rootfs /mnt/share</p>
<p>其中10.136.4.7是服务器的ip地址。</p>
<p>14. 在Ubuntu系统上安装samba方法:</p>
<p>(1). 安装samba</p>
<p>$ sudo apt-get install samba<br />
$ sudo apt-get install smbfs</p>
<p>(2). 添加linux用户</p>
<p>$ sudo useradd user1　 //添加用户名user1<br />
$ sudo passwd user1 //给用户名user1添加密码</p>
<p>(3). 给samba服务器添加用户</p>
<p>说明：登陆samba的用户必须已经是linux中的用户</p>
<p>$ sudo smbpasswd -a user1 //添加并给user1设置samba密码</p>
<p>(4). smb.conf设置</p>
<p>$ cd /etc/samb //进入设置目录<br />
$ sudo mv smb.conf　smb.conf.bak //做好备份，直接将系统默认配置文件改名<br />
$ sudo vim smb.conf //建立和配置smb.conf文件</p>
<p>[global]</p>
<p>workgroup=x1 //X1为你局域网中的工作组名<br />
server string=x2 //x2为你linux主机描述性文字，比如：samba server。<br />
security=user //samba的安全等级，user代表需要输入用户名和密码，改成share则不需要输入用户名和密码</p>
<p>[x3] //方框号中的x3这个名字可以随便取，只是在win的网上邻居中显示的共享文件夹名</p>
<p>path=/home/x4 //x4为你要共享的文件夹名，在共享前还要建立这个文件夹，并设好权限以便访问，下面会说明。<br />
valid users=user1 //这个x4共享目录只允许user1这个用户进入<br />
public=no　　　　 //no表示除了user1这个用户，其它用户在进入samba服务器后看不见x4这个目录，<br />
writable=yes　　 //允许user1在x4目录中进行读和写操作，反之no</p>
<p>(5). 重启samba服务</p>
<p>$ sudo /etc/init.d/samba restart</p>
<p>设置samba服务要注意以下两点（即两个两次）：</p>
<p>1.添加两次用户：一次添加系统用户#useradd user1；再一次是添加samba用户#smbpasswd -a user1;</p>
<p>2.设置两次权限：一次是在smb.conf中设置共享文件夹的权限：再一次是在系统中设置共享文件夹的权限#chmod 777 文件夹名。</p>
<p>15. tar的常用用法</p>
<p>tar -zcvf: tar 调用gzip打包压缩, 出来的包是.tar.gz</p>
<p>tar -jcvf: tar 调用bzip2打包压缩, 出来的包是.tar.bz2.</p>
<p>tar -zxvf 解压tar.gz</p>
<p>tar -jxvf 解压tar.bz2</p>
<p>16. 清空垃圾文件的地方</p>
<p>.tencent/file<br />
.thumbnails/<br />
.mozilla/firefox/Cache<br />
.evolution/<br />
.cache</p>
<p>17. 在Ubuntu系统上扩大磁盘的方法:</p>
<p>(1). 创建文件 (该文件可以在任何盘, /host是ubuntu安装的windows盘)</p>
<p>$ sudo dd if=/dev/zero of=root.disk bs=1024 count=1000000  (1K的块大小, 总容量1G)</p>
<p>(2). 格式化文件系统</p>
<p>$ sudo mkfs.ext3 root.disk</p>
<p>(3). 挂载到系统</p>
<p>$ mount -t ext3 -o loop root.disk /mnt</p>
<p>或者在/etc/fstab里加载</p>
<p>/[PATH]/root.disk /mnt  ext3  loop,errors=remount-ro 0 1</p>
<p>18. 在Ubuntu系统上扩大交换分区的方法:</p>
<p>(1). 创建文件</p>
<p>$ sudo dd if=/dev/zero of=swap.disk bs=1024 count=100000 (1K的块大小, 总容量100M)</p>
<p>(2). 格式化成swap</p>
<p>$ sudo mkswap swapfile</p>
<p>(3). 挂载到系统</p>
<p>$ sudo swapon swapfile</p>
<p>或者在/etc/fstab里加载</p>
<p>swapfilepath swap swap defaults 0 0
<div style="margin-top: 10px">
<p><strong>转载请注明：</strong> 转载自<a href="http://www.xiangmocheng.com/">不然你要我怎么样</a></t>        </br><strong>本文链接地址:</strong> <a href="http://www.xiangmocheng.com/2009/12/ubuntu-setting/">Ubuntu常用设置</a></div>
]]></content:encoded>
			<wfw:commentRss>http://www.xiangmocheng.com/2009/12/ubuntu-setting/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>【转贴】Linux常用命令表</title>
		<link>http://www.xiangmocheng.com/2009/09/linux-commands-sheet/</link>
		<comments>http://www.xiangmocheng.com/2009/09/linux-commands-sheet/#comments</comments>
		<pubDate>Tue, 22 Sep 2009 06:35:44 +0000</pubDate>
		<dc:creator>xiangmocheng</dc:creator>
				<category><![CDATA[Linux]]></category>

		<guid isPermaLink="false">http://xiangmocheng.yo2.cn/articles/%e3%80%90%e8%bd%ac%e8%b4%b4%e3%80%91linux%e5%b8%b8%e7%94%a8%e5%91%bd%e4%bb%a4%e8%a1%a8.html</guid>
		<description><![CDATA[点击这里下载PDF格式 －－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－ 文件命令 ls – 列出目录 ls -al – 使用格式化列出隐藏文件 cd dir – 更改目录到 dir cd – 更改到 home 目录 pwd – 显示当前目录 mkdir dir – 创建目录 dir rm file – 删除 file rm -r dir – 删除目录 dir rm -f file – 强制删除 file rm -rf dir – 强制删除目录 dir * cp file1 file2 [...]]]></description>
			<content:encoded><![CDATA[<p>点击<a href="http://xiangmocheng.com/downloads/Linux-Cheat-Sheet.pdf" target="_blank">这里</a>下载PDF格式</p>
<p>－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－</p>
<p><span style="font-size: 24px;">文件命令</span></p>
<p><strong>ls </strong>– 列出目录<br />
<strong>ls -al</strong> – 使用格式化列出隐藏文件<br />
<strong>cd dir </strong>– 更改目录到 dir<br />
<strong>cd </strong>– 更改到 home 目录<br />
<strong>pwd </strong>– 显示当前目录<br />
<strong>mkdir dir </strong>– 创建目录 dir<br />
<strong>rm file</strong> – 删除 file<br />
<strong>rm -r dir </strong>– 删除目录 dir<br />
<strong>rm -f file </strong>– 强制删除 file<br />
<strong>rm -rf dir </strong>– 强制删除目录 dir *<br />
<strong>cp file1 file2 </strong>– 将 file1 复制到 file2<br />
<strong>cp -r dir1 dir2</strong> – 将 dir1 复制到 dir2; 如果 dir2 不存在则创建它<br />
<strong>mv file1 file2 </strong>– 将 file1 重命名或移动到 file2; 如果file2 是一个存在的目录则将 file1 移动到目录 file2 中<br />
<strong>ln -s file link</strong> – 创建 file 的符号连接 link<br />
<strong>touch file</strong> – 创建 file<br />
<strong>cat &gt; file</strong> – 将标准输入添加到 file<br />
<strong>more file</strong> – 查看 file 的内容<br />
<strong>head file</strong> – 查看 file 的前 10 行<br />
<strong>tail file</strong> – 查看 file 的后 10 行<br />
<strong>tail -f file</strong> – 从后 10 行开始查看 file 的内容</p>
<p><span style="font-size: 24px;">进程管理</span></p>
<p><strong>ps</strong> – 显示当前的活动进程<br />
<strong>top</strong> – 显示所有正在运行的进程<br />
<strong>kill pid</strong> – 杀掉进程 id pid<br />
<strong>killall proc</strong> – 杀掉所有名为 proc 的进程 *<br />
<strong>bg</strong> – 列出已停止或后台的作业<br />
<strong>fg</strong> – 将最近的作业带到前台<br />
<strong>fg n</strong> – 将作业 n 带到前台</p>
<p><span style="font-size: 24px;">文件权限</span></p>
<p><strong>chmod octal file</strong> – 更改 file 的权限<br />
● 4 – 读 (r)<br />
● 2 – 写 (w)<br />
● 1 – 执行 (x)<br />
示例:<br />
chmod 777 – 为所有用户添加读、写、执行权限<br />
chmod 755 – 为所有者添加 rwx 权限, 为组和其他用户添加rx 权限<br />
chmod 777 -R dir – 为dir文件夹中所有文件添加读、写、执行权限<br />
更多选项参阅 man chmod.</p>
<p><span style="font-size: 24px;">SSH</span></p>
<p><strong>ssh user@host</strong> – 以 user 用户身份连接到 host<br />
<strong>ssh -p port user@host</strong> – 在端口 port 以 user 用户身份连接到 host<br />
<strong>ssh-copy-id user@host</strong> – 将密钥添加到 host 以实现无密码登录</p>
<p><span style="font-size: 24px;">搜索</span></p>
<p><strong>grep pattern files</strong> – 搜索 files 中匹配 pattern 的内容<br />
<strong>grep -r pattern dir</strong> – 递归搜索 dir 中匹配 pattern 的内容<br />
<strong>command | grep pattern</strong> – 搜索 command 输出中匹配pattern 的内容</p>
<p><span style="font-size: 24px;">系统信息</span></p>
<p><strong>date</strong> – 显示当前日期和时间<br />
<strong>cal</strong> – 显示当月的日历<br />
<strong>uptime</strong> – 显示系统从开机到现在所运行的时间<br />
<strong>w</strong> – 显示登录的用户<br />
<strong>whoami </strong>– 查看你的当前用户名<br />
<strong>finger user</strong> – 显示 user 的相关信息<br />
<strong>uname -a</strong> – 显示内核信息<br />
<strong>cat /proc/cpuinfo</strong> – 查看 cpu 信息<br />
<strong>cat /proc/meminfo</strong> – 查看内存信息<br />
<strong>man command</strong> – 显示 command 的说明手册<br />
<strong>df</strong> – 显示磁盘占用情况<br />
<strong>du</strong> – 显示目录空间占用情况<br />
<strong>free</strong> – 显示内存及交换区占用情况</p>
<p><span style="font-size: 24px;">压缩</span></p>
<p><strong>tar cf file.tar files</strong> – 创建包含 files 的 tar 文件file.tar<br />
<strong>tar xf file.tar</strong> – 从 file.tar 提取文件<br />
<strong>tar czf file.tar.gz files</strong> – 使用 Gzip 压缩创建tar 文件<br />
<strong>tar xzf file.tar.gz</strong> – 使用 Gzip 提取 tar 文件<br />
<strong>tar cjf file.tar.bz2</strong> – 使用 Bzip2 压缩创建 tar 文件<br />
<strong>tar xjf file.tar.bz2</strong> – 使用 Bzip2 提取 tar 文件<br />
<strong>gzip file</strong> – 压缩 file 并重命名为 file.gz<br />
<strong>gzip -d file.gz</strong> – 将 file.gz 解压缩为 file</p>
<p><span style="font-size: 24px;">网络</span></p>
<p><strong>ping host</strong> – ping host 并输出结果<br />
<strong>whois domain</strong> – 获取 domain 的 whois 信息<br />
<strong>dig domain</strong> – 获取 domain 的 DNS 信息<br />
<strong>dig -x host</strong> – 逆向查询 host<br />
<strong>wget file</strong> – 下载 file<br />
<strong>wget -c file</strong> – 断点续传<br />
<strong>ifconfig</strong> – 显示网络信息</p>
<p><span style="font-size: 24px;">安装</span></p>
<p>从源代码安装:<br />
<strong>./configure<br />
make<br />
make install<br />
dpkg -i pkg.deb</strong> – 安装包 (Debian)<br />
<strong>rpm -Uvh pkg.rpm</strong> – 安装包 (RPM)</p>
<p><span style="font-size: 24px;">快捷键</span></p>
<p><strong>Ctrl+C</strong> – 停止当前命令<br />
<strong>Ctrl+Z</strong> – 停止当前命令，并使用 <strong>fg</strong> 恢复<br />
<strong>Ctrl+D</strong> – 注销当前会话，与 <strong>exit </strong>相似<br />
<strong>Ctrl+W</strong> – 删除当前行中的字<br />
<strong>Ctrl+U</strong> – 删除整行<br />
<strong>!!</strong> &#8211; 重复上次的命令<br />
<strong>exit</strong> – 注销当前会话</p>
<p style="text-align: right;">* 小心使用。<br />
翻译/Toy</p>
<div style="margin-top: 10px">
<p><strong>转载请注明：</strong> 转载自<a href="http://www.xiangmocheng.com/">不然你要我怎么样</a></t>        </br><strong>本文链接地址:</strong> <a href="http://www.xiangmocheng.com/2009/09/linux-commands-sheet/">【转贴】Linux常用命令表</a></div>
]]></content:encoded>
			<wfw:commentRss>http://www.xiangmocheng.com/2009/09/linux-commands-sheet/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>【转贴】如何调整Linux内核启动中的驱动初始化顺序</title>
		<link>http://www.xiangmocheng.com/2009/09/how-to-change-linux-booting-sequence/</link>
		<comments>http://www.xiangmocheng.com/2009/09/how-to-change-linux-booting-sequence/#comments</comments>
		<pubDate>Thu, 10 Sep 2009 09:13:32 +0000</pubDate>
		<dc:creator>xiangmocheng</dc:creator>
				<category><![CDATA[Embedded]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[driver]]></category>
		<category><![CDATA[probe]]></category>

		<guid isPermaLink="false">http://xiangmocheng.yo2.cn/articles/%e3%80%90%e8%bd%ac%e8%b4%b4%e3%80%91%e5%a6%82%e4%bd%95%e8%b0%83%e6%95%b4linux%e5%86%85%e6%a0%b8%e5%90%af%e5%8a%a8%e4%b8%ad%e7%9a%84%e9%a9%b1%e5%8a%a8%e5%88%9d%e5%a7%8b%e5%8c%96%e9%a1%ba%e5%ba%8f.html</guid>
		<description><![CDATA[【问题】 此处我要实现的是将芯片的ID用于网卡MAC地址，网卡驱动是enc28j60_init，但是，读取芯片ID的函数，在as352x_afe_init模块中，所以要先初始化as352x_afe_init。此处，内核编译完之后，在生成的system.map中可以看到，enc28j60_init在as352x_afe_init之前，所以，无法去读芯片ID。所以我们的目标是，将as352x_afe_init驱动初始化放到enc28j60_init之前，然后才能读取芯片ID，才能用于网卡初始化的时候的，将芯片ID设置成网卡MAC地址。 【解决过程】 【1】 最简单想到的，是内核里面的 arch\arm\mach-as352x\core.c 中，去改devices设备列表中的顺序。enc28j60_init对应的是ssp_device，因为网卡初始化用到的是SPI驱动去进行和通讯的。as352x_afe_init对应的是afe_device。原先是： 把afe改到最前面： 但是，实际结果是，没有任何影响，连systemp.map生成的，那么模块初始化顺序，都没有任何变化。也就说明，想要实现驱动加载顺序的改变，改core.c里面的设备列表顺序是没有用的。 【2】 在网上看到很多帖子，主要就是这几个： 怎么确定驱动加载顺序 Linux内核驱动程序初始化顺序的调整 内核启动时,设备及驱动初始化的实现 其说明的也很清楚了，就是：Linux内核为不同驱动的加载顺序对应不同的优先级，定义了一些宏：include\linux\init.h 把自己的驱动的函数名用这些宏去定义之后，就会对应不同的加载时候的优先级。 其中，我们写驱动中所用到的module_init对应的是 而 所以，驱动对应的加载的优先级为6。 在上面的不同的优先级中，数字越小，优先级越高。同一等级的优先级的驱动，加载顺序是链接过程决定的，结果是不确定的，我们无法去手动设置谁先谁后。不同等级的驱动加载的顺序是先优先级高，后优先级低，这是可以确定的。所以，像我们之前在驱动中用： 所以，大家都是同一个优先级去初始化，最后这些驱动加载的顺序，可以查看在根目录下，生成的system.map： 。。。 c00197d8 t __initcall_alignment_init5 。。。。。 c00197f4 t __initcall_default_rootfsrootfs c00197f8 t __initcall_timer_init_sysfs6 c00197fc t __initcall_clock_dev_init6 。。。 c00198d8 t __initcall_loop_init6 c00198dc t __initcall_net_olddevs_init6 c00198e0 t __initcall_loopback_init6 c00198e4 t __initcall_enc28j60_init6 。。。 c0019900 t __initcall_as352x_spi_init6 c0019904 t __initcall_spidev_init6 [...]]]></description>
			<content:encoded><![CDATA[<p>【问题】</p>
<p>此处我要实现的是将芯片的ID用于网卡MAC地址，网卡驱动是enc28j60_init，但是，读取芯片ID的函数，在as352x_afe_init模块中，所以要先初始化as352x_afe_init。此处，内核编译完之后，在生成的system.map中可以看到，enc28j60_init在as352x_afe_init之前，所以，无法去读芯片ID。所以我们的目标是，将as352x_afe_init驱动初始化放到enc28j60_init之前，然后才能读取芯片ID，才能用于网卡初始化的时候的，将芯片ID设置成网卡MAC地址。</p>
<p>【解决过程】<span id="more-69431"></span></p>
<p>【1】</p>
<p>最简单想到的，是内核里面的</p>
<p>arch\arm\mach-as352x\core.c</p>
<p>中，去改devices设备列表中的顺序。enc28j60_init对应的是ssp_device，因为网卡初始化用到的是SPI驱动去进行和通讯的。as352x_afe_init对应的是afe_device。原先是：</p>
<pre class="brush: cpp; title: ; notranslate">static struct platform_device *devices[] =
{
	uart_device,
	nand_device,
	afe_device,
	audio_device,
	usb_device,
	as352xkbd_device,
	ssp_device,
};</pre>
<p>把afe改到最前面：</p>
<pre class="brush: cpp; title: ; notranslate">static struct platform_device *devices[] =
{
	afe_device,
	uart_device,
	nand_device,
	audio_device,
	usb_device,
	as352xkbd_device,
	ssp_device,
};</pre>
<p>但是，实际结果是，没有任何影响，连systemp.map生成的，那么模块初始化顺序，都没有任何变化。也就说明，想要实现驱动加载顺序的改变，改core.c里面的设备列表顺序是没有用的。</p>
<p>【2】</p>
<p>在网上看到很多帖子，主要就是这几个：</p>
<p><a href="http://blog.chinaunix.net/u2/72751/showart_1074704.html">怎么确定驱动加载顺序</a><br />
<a href="http://www.itjj.net/tech/OS/Linux/2006-12-21/74501.html">Linux内核驱动程序初始化顺序的调整</a><br />
<a href="http://linux.chinaunix.net/bbs/archiver/tid-1109340.html">内核启动时,设备及驱动初始化的实现</a></p>
<p>其说明的也很清楚了，就是：Linux内核为不同驱动的加载顺序对应不同的优先级，定义了一些宏：include\linux\init.h</p>
<pre class="brush: cpp; title: ; notranslate">#define pure_initcall(fn)        __define_initcall(&quot;0&quot;,fn,0)

#define core_initcall(fn)             __define_initcall(&quot;1&quot;,fn,1)
#define core_initcall_sync(fn)        __define_initcall(&quot;1s&quot;,fn,1s)
#define postcore_initcall(fn)         __define_initcall(&quot;2&quot;,fn,2)
#define postcore_initcall_sync(fn)    __define_initcall(&quot;2s&quot;,fn,2s)
#define arch_initcall(fn)             __define_initcall(&quot;3&quot;,fn,3)
#define arch_initcall_sync(fn)        __define_initcall(&quot;3s&quot;,fn,3s)
#define subsys_initcall(fn)           __define_initcall(&quot;4&quot;,fn,4)
#define subsys_initcall_sync(fn)      __define_initcall(&quot;4s&quot;,fn,4s)
#define fs_initcall(fn)               __define_initcall(&quot;5&quot;,fn,5)
#define fs_initcall_sync(fn)          __define_initcall(&quot;5s&quot;,fn,5s)
#define rootfs_initcall(fn)           __define_initcall(&quot;rootfs&quot;,fn,rootfs)
#define device_initcall(fn)           __define_initcall(&quot;6&quot;,fn,6)
#define device_initcall_sync(fn)      __define_initcall(&quot;6s&quot;,fn,6s)
#define late_initcall(fn)             __define_initcall(&quot;7&quot;,fn,7)
#define late_initcall_sync(fn)        __define_initcall(&quot;7s&quot;,fn,7s)

#define __initcall(fn) device_initcall(fn)</pre>
<p>把自己的驱动的函数名用这些宏去定义之后，就会对应不同的加载时候的优先级。</p>
<p>其中，我们写驱动中所用到的module_init对应的是</p>
<pre class="brush: cpp; title: ; notranslate">#define module_init(x) __initcall(x);</pre>
<p>而</p>
<pre class="brush: cpp; title: ; notranslate">#define __initcall(fn) device_initcall(fn)</pre>
<p>所以，驱动对应的加载的优先级为6。</p>
<p>在上面的不同的优先级中，数字越小，优先级越高。同一等级的优先级的驱动，加载顺序是链接过程决定的，结果是不确定的，我们无法去手动设置谁先谁后。不同等级的驱动加载的顺序是先优先级高，后优先级低，这是可以确定的。所以，像我们之前在驱动中用：</p>
<pre class="brush: cpp; title: ; notranslate">module_init(i2c_dev_init);
module_init(as352x_afe_init);
module_init(as352x_afe_i2c_init);
module_init(enc28j60_init);</pre>
<p>所以，大家都是同一个优先级去初始化，最后这些驱动加载的顺序，可以查看在根目录下，生成的system.map：</p>
<p>。。。<br />
c00197d8 t __initcall_alignment_init5<br />
。。。。。<br />
c00197f4 t __initcall_default_rootfsrootfs<br />
c00197f8 t __initcall_timer_init_sysfs6<br />
c00197fc t __initcall_clock_dev_init6<br />
。。。<br />
c00198d8 t __initcall_loop_init6<br />
c00198dc t __initcall_net_olddevs_init6<br />
c00198e0 t __initcall_loopback_init6<br />
c00198e4 t __initcall_enc28j60_init6<br />
。。。<br />
c0019900 t __initcall_as352x_spi_init6<br />
c0019904 t __initcall_spidev_init6<br />
。。。<br />
c0019920 t __initcall_i2c_dev_init6<br />
c0019924 t __initcall_as352x_afe_i2c_init6<br />
c0019928 t __initcall_as352x_afe_init6<br />
。。。<br />
c0019970 t __initcall_random32_reseed7<br />
c0019974 t __initcall_seqgen_init7<br />
c0019978 t __initcall_rtc_hctosys7<br />
c001997c T __con_initcall_start<br />
c001997c t __initcall_con_init<br />
c001997c T __initcall_end<br />
。。。</p>
<p>此处就是由于<br />
c0019920 t __initcall_i2c_dev_init6<br />
c0019924 t __initcall_as352x_afe_i2c_init6<br />
c0019928 t __initcall_as352x_afe_init6<br />
在<br />
c00198e4 t __initcall_enc28j60_init6<br />
之前，所以我这里才要去改。。。</p>
<p>知道原理，能想到的，就是要么把as352x_afe_init改到enc28j60_init之前一级，即优先级为5。即在驱动中，调用：fs_initcall(as352x_afe_init)；要么把enc28j60_init改到as352x_afe_init之后，即优先级为7。即在驱动中，调用：late_initcall(enc28j60_init)；但是，此处麻烦就麻烦在，如果把as352x_afe_init改到enc28j60_init之前一级，发现后面网卡初始化enc28j60_init中，虽然读取芯片ID对了，但是后面的IP-auto configure 有问题。所以放弃。如果把enc28j60_init改到as352x_afe_init之后，但是，从system.map中看到的是，优先级为7的驱动中，明显有几个驱动，也是和网卡初始化相关的，所以，这样改尝试后，还是失败了。所以，没法简单的通过调整现有的驱动的顺序，去实现顺序的调整。</p>
<p>最后，被逼无奈，想到了一个可以实现我们需求的办法，那就是，单独定义一个优先级，把afe相关的初始化都放到那里面去，这样，就可以保证，其他没什么相关的冲突了。最后证实，这样是可以实现目的的。</p>
<p>具体添加一个新的优先级的步骤如下：</p>
<p>1. 定义新的优先级</p>
<p>include\linux\init.h中：</p>
<pre class="brush: cpp; title: ; notranslate">#define pure_initcall(fn)        __define_initcall(&quot;0&quot;,fn,1)

#define core_initcall(fn)             __define_initcall(&quot;1&quot;,fn,1)
#define core_initcall_sync(fn)        __define_initcall(&quot;1s&quot;,fn,1s)
#define postcore_initcall(fn)         __define_initcall(&quot;2&quot;,fn,2)
#define postcore_initcall_sync(fn)    __define_initcall(&quot;2s&quot;,fn,2s)
#define arch_initcall(fn)             __define_initcall(&quot;3&quot;,fn,3)
#define arch_initcall_sync(fn)        __define_initcall(&quot;3s&quot;,fn,3s)
#define subsys_initcall(fn)           __define_initcall(&quot;4&quot;,fn,4)
#define subsys_initcall_sync(fn)      __define_initcall(&quot;4s&quot;,fn,4s)
#define fs_initcall(fn)               __define_initcall(&quot;5&quot;,fn,5)
#define fs_initcall_sync(fn)          __define_initcall(&quot;5s&quot;,fn,5s)
#define rootfs_initcall(fn)           __define_initcall(&quot;rootfs&quot;,fn,rootfs)
#if 1
#define prev_device_initcall(fn)      __define_initcall(&quot;6&quot;,fn,6)
#define prev_device_initcall_sync(fn) __define_initcall(&quot;6s&quot;,fn,6s)
#define device_initcall(fn)           __define_initcall(&quot;7&quot;,fn,7)
#define device_initcall_sync(fn)      __define_initcall(&quot;7s&quot;,fn,7s)
#define late_initcall(fn)             __define_initcall(&quot;8&quot;,fn,8)
#define late_initcall_sync(fn)        __define_initcall(&quot;8s&quot;,fn,8s)

#else
#define device_initcall(fn)           __define_initcall(&quot;6&quot;,fn,6)
#define device_initcall_sync(fn)      __define_initcall(&quot;6s&quot;,fn,6s)
#define late_initcall(fn)             __define_initcall(&quot;7&quot;,fn,7)
#define late_initcall_sync(fn)        __define_initcall(&quot;7s&quot;,fn,7s)
#endif</pre>
<p>2. 用对应新的宏，定义我们的驱动：prev_device_initcall(i2c_dev_init);prev_device_initcall(as352x_afe_i2c_init);prev_device_initcall(as352x_afe_init);</p>
<p>做到这里，本以为可以了，但是编译后，在system.map中，发现之前优先级为7的那几个函数，被放到system.map最后了，而不是预想的，在优先级7之后，在c001997c T __con_initcall_startc001997c t __initcall_con_initc001997c T __initcall_end之前。</p>
<p>最后，发现时没有把对应的链接文件中的宏加进去：</p>
<p>3. 在include\asm-generic\vmlinux.lds.h中：</p>
<pre class="brush: cpp; title: ; notranslate">#if 1
#define INITCALLS        \
*(.initcall0.init)       \
*(.initcall0s.init)       \
*(.initcall1.init)       \
*(.initcall1s.init)       \
*(.initcall2.init)       \
*(.initcall2s.init)       \
*(.initcall3.init)       \
*(.initcall3s.init)       \
*(.initcall4.init)       \
*(.initcall4s.init)       \
*(.initcall5.init)       \
*(.initcall5s.init)       \
*(.initcallrootfs.init)       \
*(.initcall6.init)       \
*(.initcall6s.init)       \
*(.initcall7.init)       \
*(.initcall7s.init)       \
*(.initcall8.init)       \
*(.initcall8s.init)

#else

#define INITCALLS        \
*(.initcall0.init)       \
*(.initcall0s.init)       \
*(.initcall1.init)       \
*(.initcall1s.init)       \
*(.initcall2.init)       \
*(.initcall2s.init)       \
*(.initcall3.init)       \
*(.initcall3s.init)       \
*(.initcall4.init)       \
*(.initcall4s.init)       \
*(.initcall5.init)       \
*(.initcall5s.init)       \
*(.initcallrootfs.init)       \
*(.initcall6.init)       \
*(.initcall6s.init)       \
*(.initcall7.init)       \
*(.initcall7s.init)

#endif</pre>
<p>最后，再重新编译，就可以实现我们要的，和afe相关的驱动初始化，都在网卡enc28j60_init之前了。也就可以在网卡里面读芯片ID了。当然，对应编译生成的system.map文件中，对应的通过module_init定义的驱动，优先级也都变成7了。而late_initcall对应优先级8了。</p>
<p>【3】不过，最后的最后，竟然发现网卡还是工作不正常，结果第二天，无意间发现是网卡地址设置导致网卡工作不正常的。也就是说，实际是直接将afe设置到原先的优先级5就可以的，而不用这么麻烦去改系统的东西的。。。</p>
<p>不过，至少这也是一种办法，虽然不是那么的好。。。
<div style="margin-top: 10px">
<p><strong>转载请注明：</strong> 转载自<a href="http://www.xiangmocheng.com/">不然你要我怎么样</a></t>        </br><strong>本文链接地址:</strong> <a href="http://www.xiangmocheng.com/2009/09/how-to-change-linux-booting-sequence/">【转贴】如何调整Linux内核启动中的驱动初始化顺序</a></div>
]]></content:encoded>
			<wfw:commentRss>http://www.xiangmocheng.com/2009/09/how-to-change-linux-booting-sequence/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>kmalloc vmalloc malloc区别</title>
		<link>http://www.xiangmocheng.com/2009/09/kmalloc-vmalloc-malloc-difference/</link>
		<comments>http://www.xiangmocheng.com/2009/09/kmalloc-vmalloc-malloc-difference/#comments</comments>
		<pubDate>Wed, 09 Sep 2009 06:23:55 +0000</pubDate>
		<dc:creator>xiangmocheng</dc:creator>
				<category><![CDATA[Embedded]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[kmalloc]]></category>
		<category><![CDATA[malloc]]></category>
		<category><![CDATA[vmalloc]]></category>

		<guid isPermaLink="false">http://xiangmocheng.yo2.cn/articles/kmalloc-vmalloc-malloc%e5%8c%ba%e5%88%ab.html</guid>
		<description><![CDATA[kmalloc()和vmalloc()介绍 kmalloc() 用于申请较小的、连续的物理内存 1. 以字节为单位进行分配，在&#60;linux/slab.h&#62;中 2. void *kmalloc(size_t size, int flags) 分配的内存物理地址上连续，虚拟地址上自然连续 3. gfp_mask标志：什么时候使用哪种标志？如下： &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;- 情形                                                  相应标志 &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;- 进程上下文，可以睡眠                  GFP_KERNEL 进程上下文，不可以睡眠     [...]]]></description>
			<content:encoded><![CDATA[<p><strong>kmalloc()和vmalloc()介绍</strong></p>
<p><span style="color: #ff0000;">kmalloc()</span></p>
<p>用于申请较小的、连续的物理内存</p>
<p>1. 以字节为单位进行分配，在&lt;linux/slab.h&gt;中</p>
<p>2. void *kmalloc(size_t size, int flags) 分配的内存物理地址上连续，虚拟地址上自然连续</p>
<p>3. gfp_mask标志：什么时候使用哪种标志？如下：</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<br />
情形                                                  相应标志<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<br />
进程上下文，可以睡眠                  GFP_KERNEL<br />
进程上下文，不可以睡眠               GFP_ATOMIC<br />
中断处理程序                            GFP_ATOMIC<br />
软中断                                    GFP_ATOMIC<br />
Tasklet                                  GFP_ATOMIC<br />
用于DMA的内存，可以睡眠            GFP_DMA | GFP_KERNEL<br />
用于DMA的内存，不可以睡眠         GFP_DMA | GFP_ATOMIC<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-</p>
<p>4. void kfree(const void *ptr)</p>
<p>释放由kmalloc()分配出来的内存块<br />
<span id="more-69429"></span><br />
<span style="color: #ff0000;">vmalloc()</span></p>
<p>用于申请较大的内存空间，虚拟内存是连续的</p>
<p>1. 以字节为单位进行分配，在&lt;linux/vmalloc.h&gt;中</p>
<p>2. void *vmalloc(unsigned long size) 分配的内存虚拟地址上连续，物理地址不连续</p>
<p>3. 一般情况下，只有硬件设备才需要物理地址连续的内存，因为硬件设备往往存在于MMU之外，根本不了解虚拟地址；但为了性能上的考虑，内核中一般使用kmalloc()，而只有在需要获得大块内存时才使用vmalloc()，例如当模块被动态加载到内核当中时，就把模块装载到由vmalloc()分配的内存上。</p>
<p>4.void vfree(void *addr)，这个函数可以睡眠，因此不能从中断上下文调用。</p>
<p><strong>malloc(), vmalloc()和kmalloc()区别</strong></p>
<p>[*]kmalloc和vmalloc是分配的是内核的内存,malloc分配的是用户的内存</p>
<p>[*]kmalloc保证分配的内存在物理上是连续的,vmalloc保证的是在虚拟地址空间上的连续,malloc不保证任何东西(这点是自己猜测的,不一定正确)</p>
<p>[*]kmalloc能分配的大小有限,vmalloc和malloc能分配的大小相对较大</p>
<p>[*]内存只有在要被DMA访问的时候才需要物理上连续</p>
<p>[*]vmalloc比kmalloc要慢
<div style="margin-top: 10px">
<p><strong>转载请注明：</strong> 转载自<a href="http://www.xiangmocheng.com/">不然你要我怎么样</a></t>        </br><strong>本文链接地址:</strong> <a href="http://www.xiangmocheng.com/2009/09/kmalloc-vmalloc-malloc-difference/">kmalloc vmalloc malloc区别</a></div>
]]></content:encoded>
			<wfw:commentRss>http://www.xiangmocheng.com/2009/09/kmalloc-vmalloc-malloc-difference/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>【转贴】全面的framebuffer详解（二）</title>
		<link>http://www.xiangmocheng.com/2009/08/framebuffer-2/</link>
		<comments>http://www.xiangmocheng.com/2009/08/framebuffer-2/#comments</comments>
		<pubDate>Thu, 27 Aug 2009 03:29:49 +0000</pubDate>
		<dc:creator>xiangmocheng</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Framebuffer]]></category>

		<guid isPermaLink="false">http://xiangmocheng.yo2.cn/articles/%e3%80%90%e8%bd%ac%e8%b4%b4%e3%80%91%e5%85%a8%e9%9d%a2%e7%9a%84framebuffer%e8%af%a6%e8%a7%a3%ef%bc%88%e4%ba%8c%ef%bc%89.html</guid>
		<description><![CDATA[2、 fbmem.c fbmem.c 处于Framebuffer设备驱动技术的中心位置。它为上层应用程序提供系统调用也为下一层的特定硬件驱动提供接口；那些底层硬件驱动需要用到这儿的接口来向系统内核注册它们自己. fbmem.c 为所有支持FrameBuffer的设备驱动提供了通用的接口，避免重复工作。 1) 全局变量 struct fb_info *registered_fb[FB_MAX]; int num_registered_fb; 这两变量记录了所有fb_info 结构的实例，fb_info结构描述显卡的当前状态，所有设备对应的fb_info结构都保存在这个数组中，当一个FrameBuffer设备驱动向系统注册自己时，其对应的fb_info结构就会添加到这个结构中，同时num_registered_fb 为自动加1。 static struct { const char *name; int (*init)(void); int (*setup)(void); } fb_drivers[] __initdata= { &#8230;.}; 如果FrameBuffer设备被静态链接到内核，其对应的入口就会添加到这个表中；如果是动态加载的，即使用insmod/rmmod,就不需要关心这个表。 static struct file_operations fb_ops ={ owner: THIS_MODULE, read: fb_read, write: fb_write, ioctl: fb_ioctl, mmap: fb_mmap, open: fb_open, release: fb_release }; 这是一个提供给应用程序的接口。 2）fbmem.c 实现了如下函数。 [...]]]></description>
			<content:encoded><![CDATA[<p>2、 fbmem.c<br />
<span style="color: #ff0000;">fbmem.c 处于Framebuffer设备驱动技术的中心位置</span>。<span style="color: #0000ff;">它为上层应用程序提供系统调用也为下一层的特定硬件驱动提供接口；那些底层硬件驱动需要用到这儿的接口来向系统内核注册它们自己. fbmem.c 为所有支持FrameBuffer的设备驱动提供了通用的接口，避免重复工作。</span></p>
<p>1) 全局变量</p>
<p><span style="font-family: Times New;"><strong>struct fb_info *registered_fb[FB_MAX];<br />
int num_registered_fb;</strong></span></p>
<p><span style="color: #0000ff;">这两变量记录了所有fb_info 结构的实例，fb_info结构描述显卡的当前状态，所有设备对应的fb_info结构都保存在这个数组中，当一个FrameBuffer设备驱动向系统注册自己时，其对应的fb_info结构就会添加到这个结构中，同时num_registered_fb 为自动加1。</span></p>
<p>static struct {<br />
const char *name;<br />
int (*init)(void);<br />
int (*setup)(void);<br />
} fb_drivers[] __initdata= { &#8230;.};</p>
<p><span id="more-69420"></span><span style="color: #009900;">如果FrameBuffer设备被静态链接到内核，其对应的入口就会添加到这个表中；如果是动态加载的，即使用insmod/rmmod,就不需要关心这个表。</span></p>
<p>static struct file_operations fb_ops ={<br />
owner: THIS_MODULE,<br />
read: fb_read,<br />
write: fb_write,<br />
ioctl: fb_ioctl,<br />
mmap: fb_mmap,<br />
open: fb_open,<br />
release: fb_release<br />
};</p>
<p>这是一个提供给应用程序的接口。</p>
<p>2）fbmem.c 实现了如下函数。</p>
<p><strong>register_framebuffer(struct fb_info *fb_info);<br />
unregister_framebuffer(struct fb_info *fb_info);</strong></p>
<p><span style="color: #ff0000;">这两个是提供给下层FrameBuffer设备驱动的接口，设备驱动通过这两函数向系统注册或注销自己。几乎底层设备驱动所要做的所有事情就是填充fb_info结构然后向系统注册或注销它。</span></p>
<p>（二）一个LCD显示芯片的驱动实例</p>
<p>以Skeleton LCD控制器驱动为例，在LINUX中存有一个/fb/skeleton.c的skeleton的Framebuffer驱动程序，很简单，仅仅是填充了fb_info结构，并且注册/注销自己。设备驱动是向用户程序提供系统调用接口，所以我们需要实现底层硬件操作并且定义file_operations结构来向系统提供系统调用接口，从而实现更有效的LCD控制器驱动程序。</p>
<p>1）在系统内存中分配显存</p>
<p><span style="color: #009900;">在fbmem.c文件中可以看到，file_operations 结构中的open()和release()操作不需底层支持，但read()、write()和mmap()操作需要函数fb_get_fix()的支持.因此需要重新实现函数fb_get_fix()。</span>另外还需要在系统内存中分配显存空间，大多数的LCD控制器都没有自己的显存空间，被分配的地址空间的起始地址与长度将会被填充到fb_fix_screeninfo 结构的smem_start 和smem_len 的两个变量中.被分配的空间必须是物理连续的。</p>
<p>2）实现 fb_ops 中的函数</p>
<p>用户应用程序通过ioctl()系统调用操作硬件，fb_ops 中的函数就用于支持这些操作。（注：fb_ops结构与file_operations结构不同，fb_ops是底层操作的抽象,而file_operations是提供给上层系统调用的接口，可以直接调用。）ioctl()系统调用在文件fbmem.c中实现，通过观察可以发现ioctl()命令与fb_ops’s 中函数的关系:</p>
<p>FBIOGET_VSCREENINFO fb_get_var<br />
FBIOPUT_VSCREENINFO fb_set_var<br />
FBIOGET_FSCREENINFO fb_get_fix<br />
FBIOPUTCMAP fb_set_cmap<br />
FBIOGETCMAP fb_get_cmap<br />
FBIOPAN_DISPLAY fb_pan_display</p>
<p>如果我们定义了fb_XXX_XXX 方法，用户程序就可以使用FBIOXXXX宏的ioctl()操作来操作硬件。</p>
<p>文件linux/drivers/video/fbgen.c或者linux/drivers/video目录下的其它设备驱动是比较好的参考资料。<span style="color: #ff0000;">在所有的这些函数中fb_set_var()是最重要的，它用于设定显示卡的模式和其它属性，下面是函数fb_set_var()的执行步骤：</span></p>
<p>1)检测是否必须设定模式</p>
<p>2)设定模式</p>
<p>3)设定颜色映射</p>
<p>4) 根据以前的设定重新设置LCD控制器的各寄存器。</p>
<p><span style="color: #009900;">第四步表明了底层操作到底放置在何处。在系统内存中分配显存后，显存的起始地址及长度将被设定到LCD控制器的各寄存器中（一般通过fb_set_var()函数），显存中的内容将自动被LCD控制器输出到屏幕上。另一方面，用户程序通过函数mmap()将显存映射到用户进程地址空间中，然后用户进程向映射空间发送的所有数据都将会被显示到LCD显示器上。</span></p>
<p><strong>三、FrameBuffer的应用</strong></p>
<p>（一）、一个使用FrameBuffer的例子</p>
<ol>
<li>FrameBuffer主要是根据VESA标准的实现的，所以只能实现最简单的功能。</li>
<li>由于涉及内核的问题，FrameBuffer是不允许在系统起来后修改显示模式等一系列操作。（好象很多人都想要这样干，这是不被允许的，当然如果你自己写驱动的话，是可以实现的）.</li>
<li>对FrameBuffer的操作，会直接影响到本机的所有控制台的输出，包括XWIN的图形界面。</li>
<li><span style="color: #0000ff;"><span style="color: #000000;">在struct fb_info 中的char fontname[40]; /* default font name */</span><span style="color: #ff0000;">默认的字体</span>就可以实现显示的中文化－－－－难道 篮点linux就是这样搞得？？</span></li>
</ol>
<p>好，现在可以让我们开始实现直接写屏：</p>
<p>1、打开一个FrameBuffer设备</p>
<p>2、通过mmap调用把显卡的物理内存空间映射到用户空间</p>
<p>3、直接写内存。</p>
<p>/********************************<br />
File name : fbtools.h<br />
*/</p>
<p>#ifndef _FBTOOLS_H_<br />
#define _FBTOOLS_H_<br />
#include
<linux/fb.h>
//a framebuffer device structure;<br />
typedef struct fbdev{<br />
int fb;<br />
unsigned long fb_mem_offset;<br />
unsigned long fb_mem;<br />
struct fb_fix_screeninfo fb_fix;<br />
struct fb_var_screeninfo fb_var;<br />
char dev[20];<br />
} FBDEV, *PFBDEV;</p>
<p>//open &amp; init a frame buffer<br />
//to use this function,<br />
//you must set FBDEV.dev=”/dev/fb0&#8243;<br />
//or “/dev/fbX”<br />
//it&#8217;s your frame buffer.<br />
int fb_open(PFBDEV pFbdev);</p>
<p>//close a frame buffer<br />
int fb_close(PFBDEV pFbdev);</p>
<p>//get display depth<br />
int get_display_depth(PFBDEV pFbdev);</p>
<p>//full screen clear<br />
void fb_memset(void *addr, int c, size_t len);</p>
<p>#endif</p>
<p>/******************<br />
File name : fbtools.c<br />
*/</p>
<p>#include <stdio.h><br />
#include <stdlib.h><br />
#include <fcntl.h><br />
#include <unistd.h><br />
#include <string.h><br />
#include <sys/ioctl.h><br />
#include <sys/mman.h><br />
#include <asm/page.h><br />
#include “fbtools.h”<br />
#define TRUE        1<br />
#define FALSE       0<br />
#define MAX(x,y)        ((x)>(y)?(x)y))<br />
#define MIN(x,y)        ((x)<(y)?(x)y))</p>
<p>//open &amp; init a frame buffer<br />
int fb_open(PFBDEV pFbdev)<br />
{<br />
pFbdev->fb = open(pFbdev->dev, O_RDWR);<br />
if(pFbdev->fb < 0)<br />
{<br />
printf("Error opening %s: %m. Check kernel config\n", pFbdev->dev);<br />
return FALSE;<br />
}</p>
<p>if (-1 == ioctl(pFbdev->fb,FBIOGET_VSCREENINFO,&amp;(pFbdev->fb_var)))<br />
{<br />
printf(“ioctl FBIOGET_VSCREENINFO\n”);<br />
return FALSE;<br />
}</p>
<p>if (-1 == ioctl(pFbdev->fb,FBIOGET_FSCREENINFO,&amp;(pFbdev->fb_fix)))<br />
{<br />
printf(“ioctl FBIOGET_FSCREENINFO\n”);<br />
return FALSE;<br />
}</p>
<p>//map physics address to virtual address<br />
pFbdev->fb_mem_offset = (unsigned long)(pFbdev->fb_fix.smem_start) &amp; (~PAGE_MASK);</p>
<p>pFbdev->fb_mem = (unsigned long int)mmap(NULL,<br />
pFbdev->fb_fix.smem_len + pFbdev->fb_mem_offset,<br />
PROT_READ | PROT_WRITE, MAP_SHARED, pFbdev->fb, 0);</p>
<p>if (-1L == (long) pFbdev->fb_mem)<br />
{<br />
printf(“mmap error! mem:%d offset:%d\n”, pFbdev->fb_mem, pFbdev->fb_mem_offset);<br />
return FALSE;<br />
}<br />
return TRUE;<br />
}</p>
<p>//close frame buffer<br />
int fb_close(PFBDEV pFbdev)<br />
{<br />
close(pFbdev->fb);<br />
pFbdev->fb=-1;<br />
}</p>
<p>//get display depth<br />
int get_display_depth(PFBDEV pFbdev);<br />
{<br />
if(pFbdev->fb<=0)<br />
{<br />
printf("fb device not open, open it first\n");<br />
return FALSE;<br />
}<br />
return pFbdev->fb_var.bits_per_pixel;<br />
}</p>
<p>//full screen clear<br />
void fb_memset (void *addr, int c, size_t len)<br />
{<br />
memset(addr, c, len);<br />
}</p>
<p>//use by test<br />
#define DEBUG<br />
#ifdef DEBUG<br />
main()<br />
{<br />
FBDEV fbdev;<br />
memset(&amp;fbdev, 0, sizeof(FBDEV));<br />
strcpy(fbdev.dev, “/dev/fb0&#8243;);<br />
if(fb_open(&amp;fbdev)==FALSE)<br />
{<br />
printf(“open frame buffer error\n”);<br />
return;<br />
}<br />
fb_memset(fbdev.fb_mem + fbdev.fb_mem_offset, 0, fbdev.fb_fix.smem_len);<br />
fb_close(&amp;fbdev);<br />
}</p>
<p>（二）基于Linux核心的汉字显示的尝试</p>
<p>我们以一个简单的例子来说明字符显示的过程。我们假设是在虚拟终端1（/dev/tty1）下运行一个如下的简单程序。</p>
<p>main ( )<br />
{<br />
puts(“hello, world.\n”);<br />
}</p>
<p>puts函数向缺省输出文件(/dev/tty1)发出写的系统调用write(2)。系统调用到linux核心里面对应的核心函数是console.c中的con_write()，con_write()最终会调用do_con_write( )。在do_con_write( )中负责把”hello,world.\n”这个字符串放到tty1对应的缓冲区中去。do_con_write( )还负责处理控制字符和光标的位置。让我们来看一下do_con_write()这个函数的声明。</p>
<p>static int do_con_write(struct tty_struct * tty, int from_user, const unsigned char *buf, int count)</p>
<p>其中tty是指向tty_struct结构的指针，这个结构里面存放着关于这个tty的所有信息（请参照linux/include/linux/tty.h）。Tty_struct结构中定义了通用（或高层）tty的属性（例如宽度和高度等）。在do_con_write()函数中用到了tty_struct结构中的driver_data变量。driver_data是一个vt_struct指针。在vt_struct结构中包含这个tty的序列号（我们正使用tty1，所以这个序号为1）。Vt_struct结构中有一个vc结构的数组vc_cons，这个数组就是各虚拟终端的私有数据。</p>
<p>static int do_con_write(struct tty_struct * tty, int from_user,const unsigned char *buf, int count)<br />
{<br />
struct vt_struct *vt = (struct vt_struct *)tty->driver_data;//我们用到了driver_data变量<br />
. . . . .<br />
currcons = vt->vc_num; file://我们在这里的vc_nums就是1<br />
. . . . .<br />
}</p>
<p>要访问虚拟终端的私有数据，需使用vc_cons〔currcons〕.d指针。这个指针指向的结构含有当前虚拟终端上光标的位置、缓冲区的起始地址、缓冲区大小等等。</p>
<p>“hello, world.\n”中的每一个字符都要经过conv_uni_to_pc()这个函数转换成８位的显示字符。这要做的主要目的是使不同语言的国家能把１６位的UniCode码映射到8位的显示字符集上，目前还是主要针对欧洲国家的语言，映射结果为8位，不包含对双字节（double byte）的范围。这种UNICODE到显示字符的映射关系可以由用户自行定义。在缺省的映射表上，会把中文的字符映射到其他的字符上，这是我们不希望看到也是不需要的。所以我们有两个选择∶</p>
<ol>
<li>不进行conv_uni_to_pc( )的转换。</li>
<li>加载符合双字节处理的映射关系，即对非控制字符进行1对1的不变映射。我们自己定制的符合这种映射关系的UNICODE码表是direct.uni。要想查看/装载当前系统的unicode映射表，可使外部命令loadunimap。</li>
</ol>
<p>经过conv_uni_to_pc( )转换之后，”hello,world.\n”中的字符被一个一个地填写到tty1的缓冲区中。然后do_con_write()调用下层的驱动，把缓冲区中的内容输出到显示器上（也就相当于把缓冲区的内容拷贝到VGA显存中去）。</p>
<p>sw->con_putcs(vc_cons〔currcons〕.d, (u16 *)draw_from, (u16*)draw_to-(u16 *)draw_from, y, draw_x);</p>
<p>之所以要调用底层驱动，是因为存在不同的显示设备，其对应VGA显存的存取方式也不一样。上面的Sw->con_putcs()就会调用到fbcon.c中的fbcon_putcs()函数（con_putcs是一个函数的指针，在Framebuffer模式下指向fbcon_putcs()函数）。也就是说在do_con_write()函数中是直接调用了fbcon_putcs()函数来进行字符的绘制。比如说在256色模式下，真正负责输出的函数是void<br />
fbcon_cfb8_putcs(struct vc_data *conp, struct display *p,const unsigned short *s, int count, int yy, int xx)
<div style="margin-top: 10px">
<p><strong>转载请注明：</strong> 转载自<a href="http://www.xiangmocheng.com/">不然你要我怎么样</a></t>        </br><strong>本文链接地址:</strong> <a href="http://www.xiangmocheng.com/2009/08/framebuffer-2/">【转贴】全面的framebuffer详解（二）</a></div>
]]></content:encoded>
			<wfw:commentRss>http://www.xiangmocheng.com/2009/08/framebuffer-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>【转贴】全面的framebuffer详解（一）</title>
		<link>http://www.xiangmocheng.com/2009/08/framebuffer-1/</link>
		<comments>http://www.xiangmocheng.com/2009/08/framebuffer-1/#comments</comments>
		<pubDate>Thu, 27 Aug 2009 03:28:10 +0000</pubDate>
		<dc:creator>xiangmocheng</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Framebuffer]]></category>

		<guid isPermaLink="false">http://xiangmocheng.yo2.cn/articles/%e3%80%90%e8%bd%ac%e8%b4%b4%e3%80%91%e5%85%a8%e9%9d%a2%e7%9a%84framebuffer%e8%af%a6%e8%a7%a3%ef%bc%88%e4%b8%80%ef%bc%89.html</guid>
		<description><![CDATA[原文地址：http://blog.chinaunix.net/u1/51844/showart_1710984.html 一、FrameBuffer的原理 FrameBuffer 是出现在 2.2.xx 内核当中的一种驱动程序接口。 Linux是工作在保护模式下，所以用户态进程是无法象DOS那样使用显卡BIOS里提供的中断调用来实现直接写屏，Linux抽象出FrameBuffer这个设备来供用户态进程实现直接写屏。Framebuffer机制模仿显卡的功能，将显卡硬件结构抽象掉，可以通过Framebuffer的读写直接对显存进行操作。用户可以将Framebuffer看成是显示内存的一个映像，将其映射到进程地址空间之后，就可以直接进行读写操作，而写操作可以立即反应在屏幕上。这种操作是抽象的，统一的。用户不必关心物理显存的位置、换页机制等等具体细节。这些都是由Framebuffer设备驱动来完成的。 但Framebuffer本身不具备任何运算数据的能力，就只好比是一个暂时存放水的水池，CPU将运算后的结果放到这个水池，水池再将结果流到显示器，中间不会对数据做处理。应用程序也可以直接读写这个水池的内容.在这种机制下，尽管Framebuffer需要真正的显卡驱动的支持，但所有显示任务都有CPU完成，因此CPU负担很重。 framebuffer的设备文件一般是 /dev/fb0、/dev/fb1 等等。可以用命令: #dd if=/dev/zero of=/dev/fb 清空屏幕。 如果显示模式是 1024&#215;768-8 位色，用命令：$ dd if=/dev/zero of=/dev/fb0 bs=1024 count=768 清空屏幕； 用命令: #dd if=/dev/fb of=fbfile 可以将fb中的内容保存下来； 可以重新写回屏幕: #dd if=fbfile of=/dev/fb； 在使用Framebuffer时，Linux是将显卡置于图形模式下的。 在应用程序中，一般通过将 FrameBuffer 设备映射到进程地址空间的方式使用，比如下面的程序就打开 /dev/fb0设备，并通过 mmap 系统调用进行地址映射，随后用 memset 将屏幕清空（这里假设显示模式是 1024&#215;768-8位色模式，线性内存模式）： int fb; unsigned char* fb_mem; fb = open (“/dev/fb0&#8243;, O_RDWR); fb_mem = [...]]]></description>
			<content:encoded><![CDATA[<p>原文地址：<a href="http://blog.chinaunix.net/u1/51844/showart_1710984.html">http://blog.chinaunix.net/u1/51844/showart_1710984.html</a></p>
<p><strong>一、FrameBuffer的原理</strong></p>
<p>FrameBuffer 是出现在 2.2.xx 内核当中的一种驱动程序接口。</p>
<p>Linux是工作在保护模式下，所以用户态进程是无法象DOS那样使用显卡BIOS里提供的中断调用来实现直接写屏，Linux抽象出FrameBuffer这个设备来供用户态进程实现直接写屏。Framebuffer机制模仿显卡的功能，将显卡硬件结构抽象掉，可以通过Framebuffer的读写直接对显存进行操作。用户可以将Framebuffer看成是显示内存的一个映像，将其映射到进程地址空间之后，就可以直接进行读写操作，而写操作可以立即反应在屏幕上。这种操作是抽象的，统一的。用户不必关心物理显存的位置、换页机制等等具体细节。这些都是由Framebuffer设备驱动来完成的。</p>
<p>但Framebuffer本身不具备任何运算数据的能力，就只好比是一个暂时存放水的水池，CPU将运算后的结果放到这个水池，水池再将结果流到显示器，中间不会对数据做处理。应用程序也可以直接读写这个水池的内容.在这种机制下，尽管Framebuffer需要真正的显卡驱动的支持，但所有显示任务都有CPU完成，因此CPU负担很重。</p>
<p><span id="more-69419"></span>framebuffer的设备文件一般是 /dev/fb0、/dev/fb1 等等。可以用命令: #dd if=/dev/zero of=/dev/fb 清空屏幕。</p>
<p>如果显示模式是 1024&#215;768-8 位色，用命令：$ dd if=/dev/zero of=/dev/fb0 bs=1024 count=768 清空屏幕；</p>
<p>用命令: #dd if=/dev/fb of=fbfile  可以将fb中的内容保存下来；</p>
<p>可以重新写回屏幕: #dd if=fbfile of=/dev/fb；</p>
<p><span style="color: #ff0000;">在使用Framebuffer时，Linux是将显卡置于图形模式下的。</span></p>
<p>在应用程序中，一般通过将 FrameBuffer 设备映射到进程地址空间的方式使用，比如下面的程序就打开 /dev/fb0设备，并通过 mmap 系统调用进行地址映射，随后用 memset 将屏幕清空（这里假设显示模式是 1024&#215;768-8位色模式，线性内存模式）：</p>
<p>int fb;<br />
unsigned char* fb_mem;<br />
fb = open (“/dev/fb0&#8243;, O_RDWR);<br />
fb_mem = mmap (NULL, 1024*768, PROT_READ|PROT_WRITE,MAP_SHARED,fb,0);<br />
memset (fb_mem, 0, 1024*768); <span style="font-family: 幼圆; color: #ff0000;">//这个命令应该只有在root可以执行</span></p>
<p>FrameBuffer 设备还提供了若干 ioctl 命令，通过这些命令，可以获得显示设备的一些固定信息（比如显示内存大小）、与显示模式相关的可变信息（比如分辨率、象素结构、每扫描线的字节宽度），以及伪彩色模式下的调色板信息等等。</p>
<p><span style="color: #0000ff;">通过 FrameBuffer设备，还可以获得当前内核所支持的加速显示卡的类型（通过固定信息得到），这种类型通常是和特定显示芯片相关的。比如目前最新的内核（2.4.9）中，就包含有对 S3、Matrox、nVidia、3Dfx 等等流行显示芯片的加速支持。在获得了加速芯片类型之后，应用程序就可以将 PCI设备的内存I/O（memio）映射到进程的地址空间。这些 memio一般是用来控制显示卡的寄存器，通过对这些寄存器的操作，应用程序就可以控制特定显卡的加速功能。</span> PCI设备可以将自己的控制寄存器映射到物理内存空间，而后，对这些控制寄存器的访问，给变成了对物理内存的访问。因此，这些寄存器又被称为”memio”。一旦被映射到物理内存，Linux 的普通进程就可以通过 mmap 将这些内存 I/O 映射到进程地址空间，这样就可以直接访问这些寄存器了。</p>
<p>当然，因为不同的显示芯片具有不同的加速能力，对memio的使用和定义也各自不同，这时，就需要针对加速芯片的不同类型来编写实现不同的加速功能。比如大多数芯片都提供了对矩形填充的硬件加速支持，但不同的芯片实现方式不同，这时，就需要针对不同的芯片类型编写不同的用来完成填充矩形的函数。</p>
<p>FrameBuffer 只是一个提供显示内存和显示芯片寄存器从物理内存映射到进程地址空间中的设备。所以，对于应用程序而言，如果希望在 FrameBuffer 之上进行图形编程，还需要自己动手完成其他许多工作。</p>
<p><strong>二、FrameBuffer在Linux中的实现和机制</strong></p>
<p><strong></strong>Framebuffer对应的源文件在linux/drivers/video/目录下。总的抽象设备文件为fbcon.c，在这个目录下还有与各种显卡驱动相关的源文件。   <span style="color: #ff0000;">//这个文件要好好看看</span></p>
<p>(一)、分析Framebuffer设备驱动</p>
<p>需要特别提出的是在INTEL平台上，老式的VESA 1.2卡，如CGA/EGA卡，是不能支持Framebuffer的，因为Framebuffer要求显卡支持线性帧缓冲，即CPU可以访问显缓冲中的每一位，但是VESA 1.2 卡只能允许CPU一次访问64K的地址空间。</p>
<p>FrameBuffer设备驱动基于如下两个文件：</p>
<p>1) linux/include/linux/fb.h<br />
2) linux/drivers/video/fbmem.c</p>
<p>下面分析这两个文件。</p>
<p>1、fb.h</p>
<p>几乎主要的结构都是在这个中文件定义的。这些结构包括：</p>
<p>1）fb_var_screeninfo</p>
<p>这个结构描述了显示卡的特性：</p>
<p><span style="color: #ff0000;"><span style="color: #ff0000;">NOTE::::</span> </span><span style="color: #009900;">__u32 是表示 unsigned 不带符号的 32 bits 的数据类型，其余类推。这是 Linux 内核中所用到的数据类型，如果是开发用户空间（user-space）的程序，可以根据具体计算机平台的情况，用 unsigned long 等等来代替</span></p>
<p>struct fb_var_screeninfo<br />
{<br />
__u32 xres; /* visible resolution */   <span style="color: #ff0000;">//可视区域<br />
</span>__u32 yres;<br />
__u32 xres_virtual; /* virtual resolution */  <span style="color: #ff0000;">//可视区域</span><br />
__u32 yres_virtual;<br />
__u32 xoffset; /* offset from virtual to visible resolution */ <span style="color: #ff0000;">//可视区域的偏移<br />
</span>__u32 yoffset;</p>
<p>__u32 bits_per_pixel; /* guess what */  <span style="color: #ff0000;">//每一象素的bit数</span><br />
__u32 grayscale; /* != 0 Gray levels instead of colors */<span style="color: #ff0000;">//等于零就成黑白</span></p>
<p>struct fb_bitfield red; /* bitfield in fb mem if true color, */<span style="color: #ff0000;">真彩的bit机构<br />
</span>struct fb_bitfield green; /* else only length is significant */<br />
struct fb_bitfield blue;<br />
struct fb_bitfield transp; /* transparency */  <span style="color: #ff0000;">透明</span></p>
<p>__u32 nonstd; /* != 0 Non standard pixel format */ <span style="color: #ff0000;">不是标准格式</span></p>
<p>__u32 activate; /* see FB_ACTIVATE_* */</p>
<p>__u32 height; /* height of picture in mm */ <span style="color: #ff0000;">内存中的图像高度</span><br />
__u32 width; /* width of picture in mm */ <span style="color: #ff0000;">内存中的图像宽度</span></p>
<p>__u32 accel_flags; /* acceleration flags (hints) */ <span style="color: #ff0000;">加速标志</span></p>
<p>/* Timing: All values in pixclocks, except pixclock (of course) */</p>
<p><span style="color: #ff0000;">时序-_-这些部分就是显示器的显示方法了，可以找相关的资料看看</span><br />
__u32 pixclock; /* pixel clock in ps (pico seconds) */<br />
__u32 left_margin; /* time from sync to picture */<br />
__u32 right_margin; /* time from picture to sync */<br />
__u32 upper_margin; /* time from sync to picture */<br />
__u32 lower_margin;<br />
__u32 hsync_len; /* length of horizontal sync */  <span style="color: #ff0000;">水平可视区域</span><br />
__u32 vsync_len; /* length of vertical sync */   <span style="color: #ff0000;">垂直可视区域<br />
</span>__u32 sync; /* see FB_SYNC_* */<br />
__u32 vmode; /* see FB_VMODE_* */<br />
__u32 reserved[6]; /* Reserved for future compatibility */<span style="color: #ff0000;"> 备用－以后开发</span><br />
};</p>
<p>2) fb_fix_screeninfon</p>
<p>这个<span style="color: #0000ff;">结构在显卡被设定模式后创建，它描述显示卡的属性，并且系统运行时不能被修改</span>；比如FrameBuffer内存的起始地址。它依赖于被设定的模式，当一个模式被设定后，内存信息由显示卡硬件给出，内存的位置等信息就不可以修改。</p>
<p>struct fb_fix_screeninfo {<br />
char id[16]; /* identification string eg “TT Builtin” */<span style="color: #ff0000;">ID<br />
</span>unsigned long smem_start; /* Start of frame buffer mem */ <span style="color: #ff0000;">内存起始</span><br />
/* (physical address) */ <span style="color: #ff0000;">物理地址</span><br />
__u32 smem_len; /* Length of frame buffer mem */ <span style="color: #ff0000;">内存大小</span><br />
__u32 type; /* see FB_TYPE_* */<br />
__u32 type_aux; /* Interleave for interleaved Planes */<span style="color: #ff0000;">插入区域？</span><br />
__u32 visual; /* see FB_VISUAL_* */<br />
__u16 xpanstep; /* zero if no hardware panning */<span style="color: #ff0000;">没有硬件设备就为零</span><br />
__u16 ypanstep; /* zero if no hardware panning */<br />
__u16 ywrapstep; /* zero if no hardware ywrap */<br />
__u32 line_length; /* length of a line in bytes */ <span style="color: #ff0000;">一行的字节表示<br />
</span>unsigned long mmio_start; /* Start of Memory Mapped I/O */<span style="color: #ff0000;">内存映射的I/O起始<br />
</span>/* (physical address) */<br />
__u32 mmio_len; /* Length of Memory Mapped I/O */ <span style="color: #ff0000;">I/O的大小<br />
</span>__u32 accel; /* Type of acceleration available */ <span style="color: #ff0000;">可用的加速类型<br />
</span>__u16 reserved[3]; /* Reserved for future compatibility */<br />
};</p>
<p>3) fb_cmap</p>
<p>描述设备无关的颜色映射信息。可以通过<span style="color: #0000ff;">FBIOGETCMAP 和 FBIOPUTCMAP</span> 对应的ioctl操作设定或获取颜色映射信息.</p>
<p>struct fb_cmap {<br />
__u32 start; /* First entry */ <span style="color: #ff0000;">第一个入口<br />
</span>__u32 len; /* Number of entries */ <span style="color: #ff0000;">入口的数字</span><br />
__u16 *red; /* Red values */ <span style="color: #ff0000;">红</span><br />
__u16 *green;<br />
__u16 *blue;<br />
__u16 *transp; /* transparency, can be NULL */<span style="color: #ff0000;"> 透明，可以为零<br />
</span>};</p>
<p>4) fb_info</p>
<p><span style="color: #009900;">定义当显卡的当前状态；fb_info结构仅在内核中可见，在这个结构中有一个fb_ops指针， 指向驱动设备工作所需的函数集。</span></p>
<p>struct fb_info {<br />
char modename[40]; /* default video mode */ <span style="color: #ff0000;">默认的视频卡类型</span><br />
kdev_t node;<br />
int flags;<br />
int open; /* Has this been open already ? */ <span style="color: #ff0000;">被打开过么？<br />
</span>#define FBINFO_FLAG_MODULE 1 /* Low-level driver is a module */<br />
struct fb_var_screeninfo var; /* Current var */ <span style="color: #ff0000;">现在的视频信息<br />
</span>struct fb_fix_screeninfo fix; /* Current fix */ <span style="color: #ff0000;">修正的信息<br />
</span>struct fb_monspecs monspecs; /* Current Monitor specs */ <span style="color: #ff0000;">现在的显示器模式</span><br />
struct fb_cmap cmap; /* Current cmap */ <span style="color: #ff0000;">当前优先级</span><br />
struct fb_ops *fbops;<br />
char *screen_base; /* Virtual address */ <span style="color: #ff0000;">物理基址<br />
</span>struct display *disp; /* initial display variable */<span style="color: #ff0000;">初始化<br />
</span>struct vc_data *display_fg; /* Console visible on this display */<br />
char fontname[40]; /* default font name */<span style="color: #ff0000;">默认的字体<br />
</span>devfs_handle_t devfs_handle; /* Devfs handle for new name */<br />
devfs_handle_t devfs_lhandle; /* Devfs handle for compat. symlink */<span style="color: #ff0000;">兼容<br />
</span>int (*changevar)(int); /* tell console var has changed */ <span style="color: #ff0000;">告诉console变量修改了<br />
</span>int (*switch_con)(int, struct fb_info*);<br />
/* tell fb to switch consoles */ <span style="color: #ff0000;">告诉fb选择consoles</span><br />
int (*updatevar)(int, struct fb_info*);<br />
/* tell fb to update the vars */ <span style="color: #ff0000;">告诉fb更新变量<br />
</span>void (*blank)(int, struct fb_info*); /* tell fb to (un)blank the screen */<span style="color: #ff0000;">告诉fb使用黑白模式（或者不黑）</span><br />
/* arg = 0: unblank */<span style="color: #ff0000;">arg＝0的时候黑白模式<br />
</span>/* arg &gt; 0: VESA level (arg-1) */ <span style="color: #ff0000;">arg&gt;0时候选择VESA模式<br />
</span>void *pseudo_palette; /* Fake palette of 16 colors and<br />
the cursor&#8217;s color for non<br />
palette mode */  <span style="color: #ff0000;">修正调色板</span><br />
/* From here on everything is device dependent */ <span style="color: #ff0000;">现在就可以使用了<br />
</span>void *par;<br />
};</p>
<p>5) struct fb_ops</p>
<p>用户应用可以使用ioctl()系统调用来操作设备，这个结构就是用一支持ioctl()的这些操作的。</p>
<p>struct fb_ops {<br />
/* open/release and usage marking */<br />
struct module *owner;<br />
int (*fb_open)(struct fb_info *info, int user);<br />
int (*fb_release)(struct fb_info *info, int user);<br />
/* get non settable parameters */<br />
int (*fb_get_fix)(struct fb_fix_screeninfo *fix, int con,<br />
struct fb_info *info);<br />
/* get settable parameters */<br />
int (*fb_get_var)(struct fb_var_screeninfo *var, int con,<br />
struct fb_info *info);<br />
/* set settable parameters */<br />
int (*fb_set_var)(struct fb_var_screeninfo *var, int con,<br />
struct fb_info *info);<br />
/* get colormap */<br />
int (*fb_get_cmap)(struct fb_cmap *cmap, int kspc, int con,<br />
struct fb_info *info);<br />
/* set colormap */<br />
int (*fb_set_cmap)(struct fb_cmap *cmap, int kspc, int con,<br />
struct fb_info *info);<br />
/* pan display (optional) */<br />
int (*fb_pan_display)(struct fb_var_screeninfo *var, int con,<br />
struct fb_info *info);<br />
/* perform fb specific ioctl (optional) */<br />
int (*fb_ioctl)(struct inode *inode, struct file *file, unsigned int cmd,<br />
unsigned long arg, int con, struct fb_info *info);<br />
/* perform fb specific mmap */<br />
int (*fb_mmap)(struct fb_info *info, struct file *file, struct vm_area_struct *vma);<br />
/* switch to/from raster image mode */<br />
int (*fb_rasterimg)(struct fb_info *info, int start);<br />
};</p>
<p>6) structure map</p>
<p>struct fb_info_gen | struct fb_info | fb_var_screeninfo<br />
|                        |                    | fb_fix_screeninfo<br />
|                        |                    | fb_cmap<br />
|                        |                    | modename[40]<br />
|                        |                    | fb_ops &#8212;|&#8212;&gt;ops on var<br />
|                        |                    | &#8230;           | fb_open<br />
|                        |                    |               | fb_release<br />
|                        |                    |               | fb_ioctl<br />
|                        |                    |               | fb_mmap<br />
| struct fbgen_hwswitch</p>
<p>\&#8212;&#8211;|-&gt; detect<br />
| encode_fix<br />
| encode_var<br />
| decode_fix<br />
| decode_var<br />
| get_var<br />
| set_var<br />
| getcolreg<br />
| setcolreg<br />
| pan_display<br />
| blank<br />
| set_disp</p>
<p>[编排有点困难，第一行的第一条竖线和下面的第一列竖线对齐，第一行的第二条竖线和下面的第二列竖线对齐就可以了]<br />
这个结构 fbgen_hwswitch抽象了硬件的操作.虽然它不是必需的，但有时候很有用.
<div style="margin-top: 10px">
<p><strong>转载请注明：</strong> 转载自<a href="http://www.xiangmocheng.com/">不然你要我怎么样</a></t>        </br><strong>本文链接地址:</strong> <a href="http://www.xiangmocheng.com/2009/08/framebuffer-1/">【转贴】全面的framebuffer详解（一）</a></div>
]]></content:encoded>
			<wfw:commentRss>http://www.xiangmocheng.com/2009/08/framebuffer-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ubuntu手动安装Nvidia 6100显卡驱动</title>
		<link>http://www.xiangmocheng.com/2009/06/how-to-install-nvidia-6100-driver-on-ubuntu/</link>
		<comments>http://www.xiangmocheng.com/2009/06/how-to-install-nvidia-6100-driver-on-ubuntu/#comments</comments>
		<pubDate>Mon, 15 Jun 2009 08:44:07 +0000</pubDate>
		<dc:creator>xiangmocheng</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[6100]]></category>
		<category><![CDATA[Ubuntu]]></category>

		<guid isPermaLink="false">http://xiangmocheng.yo2.cn/articles/ubuntu%e6%89%8b%e5%8a%a8%e5%ae%89%e8%a3%85nvidia-6100%e6%98%be%e5%8d%a1%e9%a9%b1%e5%8a%a8.html</guid>
		<description><![CDATA[Ubuntu9.04自动下载的NVIDA驱动不适合Geforce 6100，安装后无法进入桌面环境。所以在这里介绍下手动安装方法，安装前最好已经更新好软件包： 1.下载合适的驱动包： 到http://www.nvidia.com/object/unix.html下载，对于32位机器可以直接点击这里。下载完成后copy到自己的主目录下（不要放在桌面，免得命令行模式下进不去）。 2.安装开始，首先我们要退出桌面环境进入命令行模式（现在先不要做！）： Ctrl+Alt+F1 回到桌面环境按Ctrl+Alt+F7。 登录后，停止GDM进程： sudo /etc/init.d/gdm stop 运行驱动安装包： sudo sh /home/[yourusername]/NVIDIA-Linux-x86-185.18.14-pkg1.run 接下来安装包会询问你几件事： Accept the licence agreement;（接受许可协议） Say No when prompted to check for a kernel interface to download;（从Nvidia下载内核接口，NO） Hit OK when informed the installer will need to compile a new kernel interface;（编译内核接口，OK） Assuming all went well, answer Yes to allowing the [...]]]></description>
			<content:encoded><![CDATA[<p>Ubuntu9.04自动下载的NVIDA驱动不适合Geforce 6100，安装后无法进入桌面环境。所以在这里介绍下手动安装方法，安装前最好已经更新好软件包：</p>
<p>1.下载合适的驱动包：<br />
到http://www.nvidia.com/object/unix.html下载，对于32位机器可以直接点击<a href="http://us.download.nvidia.com/XFree86/Linux-x86/185.18.14/NVIDIA-Linux-x86-185.18.14-pkg1.run" target="_blank">这里</a>。下载完成后copy到自己的主目录下（不要放在桌面，免得命令行模式下进不去）。</p>
<p>2.安装开始，首先我们要退出桌面环境进入命令行模式（现在先不要做！）：</p>
<p>Ctrl+Alt+F1</p>
<p>回到桌面环境按Ctrl+Alt+F7。</p>
<p>登录后，停止GDM进程：</p>
<p>sudo /etc/init.d/gdm stop</p>
<p>运行驱动安装包：</p>
<p>sudo sh /home/[yourusername]/NVIDIA-Linux-x86-185.18.14-pkg1.run</p>
<p>接下来安装包会询问你几件事：</p>
<p>Accept the licence agreement;（接受许可协议）</p>
<p>Say No when prompted to check for a kernel interface to download;（从Nvidia下载内核接口，NO）</p>
<p>Hit OK when informed the installer will need to compile a new kernel interface;（编译内核接口，OK）</p>
<p>Assuming all went well, answer Yes to allowing the installer to run nvidia-xconfig；（安装最后会问你是否允许安装文件配置config文件，Yes）</p>
<p>重启就OK啦。
<div style="margin-top: 10px">
<p><strong>转载请注明：</strong> 转载自<a href="http://www.xiangmocheng.com/">不然你要我怎么样</a></t>        </br><strong>本文链接地址:</strong> <a href="http://www.xiangmocheng.com/2009/06/how-to-install-nvidia-6100-driver-on-ubuntu/">Ubuntu手动安装Nvidia 6100显卡驱动</a></div>
]]></content:encoded>
			<wfw:commentRss>http://www.xiangmocheng.com/2009/06/how-to-install-nvidia-6100-driver-on-ubuntu/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

