2008年3月31日 星期一

核心進行開檔,讀檔與寫檔的程式作為範例

透過

oldfs=get_fs();

set_fs(KERNEL_DS);

把目前執行程式current可存取的記憶體範圍設定為4GB,這樣當Kernel-Mode的程式碼呼叫函式時,就可以存取目前在3-4GB記憶體範圍內核心程式碼所包含的參數. 在開檔動作之後,就可以透過filp->f_pos移動檔案指標,寫入檔案,與讀取檔案的動作,而且這些動作所帶入的參數都是位於核心所屬的記憶體範圍內(3GB-4GB).

REF:http://loda.zhupiter.com/LinuxProtectModeArch.htm

gcc -D__KERNEL__ -DMODULE -Wall -O2 -I/usr/include/linux -I/usr/src/linux/include -c kernel.c -o kernel.o
#include <linux/kernel.h>

#include <linux/module.h>

#include <linux/errno.h>

//

#include <asm/atomic.h>

#include <asm/processor.h>

#include <asm/uaccess.h>

#include <linux/file.h>

//

char buf[]="This is a kernel-mode file operation testing program";

char b_buf[128];

//

int init_module(void)

{

char filename[]="/linux.tmp";

struct file *filp;

int r;

mm_segment_t oldfs;

//

printk("\ninit_module\n\n");

//

oldfs=get_fs();

set_fs(KERNEL_DS);

filp=filp_open(filename,O_CREAT|O_RDWR,0777);

if(IS_ERR(filp))

{

printk("\nFile Open Error:%s\n",filename);

return 0;

}

if(!filp->f_op)

{

printk("\nFile Operation Method Error!!\n");

return 0;

}

//

printk("\nFile Offset Position:%xh\n",(unsigned)filp->f_pos);

r=filp->f_op->write(filp,buf,sizeof(buf),&filp->f_pos);

printk("\nWrite :%xh bytes Offset=%xh\n",r,(unsigned)filp->f_pos);

//

filp->f_pos=0x00;

r=filp->f_op->read(filp,b_buf,sizeof(b_buf),&filp->f_pos);

printk("\nRead %xh bytes %s\n",r,b_buf);

filp_close(filp,NULL);

set_fs(oldfs);

return 0;

}

//

void cleanup_module(void)

{

printk("\nclean_module\n\n");

}

2008年3月9日 星期日

PC上使用jffs2

製作jffs2 image
#mkfs.jffs2 -d /jffs2 -o /jffs2.img -l iVU

#/sbin/mtd.ready.sh
#!/bin/sh
modprobe mtdcore
modprobe jffs2
modprobe mtdram total_size=32768 erase_size=256
modprobe mtdchar
modprobe mtdblock

會產生/dev/mtd0 及/mtd/mtdblock0檔案
dd if=/jffs2.img of=/dev/mtd0
mount /dev/mtdblock0 /mnt


REF:http://martin-yang.blogspot.com/2007/04/pcjffs2-imagemount-jffs2loop-back.html

2008年3月5日 星期三

關掉吃效能的cidaemon

建議若是使用NT4/2000/XP系統的人,遇到PF檔使用量莫名激增,致使效能降低,無法恢復正常,可以試試看下面的方法。


CiDaemon.exe是WindowsNT4/2000/XP下的指引服務,它會預先讀取硬碟內所有的資料並作連結索引,簡單的說就是作超文 字連結,通常應該不會造成問題,但是在某些狀況下它會佔據大量記憶體及CPU處理序,此時可進入(WinNT4)控制台或是(Win2000/XP)系統 管理工具將它停掉。

或進入msconfig將它關掉,可是這個程式並不是放在startup裡面,它會不定時執行(我三次狀況,一次是結 束遊戲,一次是檢查磁碟錯誤之後,最後是重新灌備份的ghost檔之後重新啟動),因此沒有辦法用傳統 :rolleyes: 的方法關掉,我先找到TweakHound-調校最佳效能的地方找,終於讓我找到關於服務如何關閉,接著我看了BlackViper寫的有關於服務 (service)的網頁,他提到如何關掉索引(Indexing)的服務,在XP下(因為我用XP)有兩個方法:

1. 第一個是執行"services.msc",這樣就會開啟[服務]這個程式框,接著在右邊的的樹狀目錄找到"Indexing Service",按下滑鼠右鍵,選擇[內容],在[啟動類型]那邊選擇"已停用"就可以了。

2. 第二個就是到[程式集]中找[系統管理工具]的[元件服務],從中在選[服務(本機)]也可以。

REF:http://blog.pixnet.net/yunchii/post/835334

2008年3月3日 星期一

不定參數的 C 函式

只要寫過 C 程式的人,都用過 printf 這個函式,也都知道它可是一個
不定參數的函式,了解它的運作方式,你也可以實作自己的不定參數的
函式。
先看一下 printf 的原型:
int printf( const char *format [, argument]... );
在format後面的參數不但不定個數且型態也是不定的。
這些參數是one bye one 的堆在stack裡面。
printf這個函式如何正確的取出這些參數?
秘訣就在 format,函式根據format裡的格式("%d %f...")
依序把堆在stack裡的參數取出。而這取出的動作就是用到
va_arg, va_end, va_start這三個macro再加上va_list。
va_list 事實上是一個 char * 的型態:
typedef char * va_list;
其它的三個macro的例子(不同的平台會有不太一樣的macro)
/* A guess at the proper definitions for other platforms */
#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )

#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )
#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
#define va_end(ap) ( ap = (va_list)0 )

這三個macro若看得懂,對了解它們的運作會很有幫助;看不太懂也沒關係
,看一下下面的說明也差不可以了。
首先 va_start 把取出的指標(va_list)指到第一個不定參數。
然後就可以用 va_arg 以指定的型態從va_list取出資料並把va_list
指標移到下一個位置(例如取走了一個int 4 bytes 的資料, va_list便會加 4)
當取完資料後便可使用 va_end 把 va_list 歸零(這個macro應看得懂吧)。
其實對大部份的應用來說 va_end 做不做是沒太大的關係的。

下面是一個不定參數函式的範例(轉載自MSDN):
int average( int first, ... )
{
int count = 0, sum = 0, i = first;
va_list marker;

va_start( marker, first ); /* Initialize variable arguments. */
while( i != -1 )
{
sum += i;
count++;
i = va_arg( marker, int);
}
va_end( marker ); /* Reset variable arguments. */
return( sum ? (sum / count) : 0 );
}

註:_INTSIZEOF 是 int size memory alignment,如果你不知那是什麼
  就把 _INTSIZEOF 看成這樣的定義會比較容易理解:
#define _INTSIZEOF(n) sizeof(n)
為什麼不直接用sizeof(n)就好了,使用 macro 是為了跨平台時能保持運
作正確。若傳了一個2 bytrs的不定參數(如 short),但在一個 32 bits的
平台推入堆疊就會是4個bytes(32 bits)不是2 bytes,所以參數的取出
就要非常的小心。使用_INTSIZEOF 在於保證引數指標移動的正確。

=================================================
#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )

這應屬概數問題吧!?
有n個蘋果,無條件進位取x的倍數,會是幾個蘋果?
A. (n+(x-1)) - ((n+(x-1))%x)
如果x是2的m次方(x=1,2,4,8...),那麼上面的A.公式可簡化為:
B. (n+(x-1)) & ~(x-1)
因為 :
令 N=(n+(x-1)) 那麼 A.公式可以說成
N減去N除以x的餘數
如果x是2的幾次方(1,2,4,8...),N減去N除以x的餘數可以寫成:
& ~(x-1)
why?
x=1-->N減去N除以1的餘數
= N & (0xFF..FF)
= N & ~(1-1)

x=2-->N減去N除以2的餘數
= N & (0xFF..FE)
= N & ~(2-1)

x=4-->N減去N除以4的餘數
= N & (0xFF..FC)
= N & ~(4-1)

::::::::::::::::::::::::::::::::::
最後把B.公式以 n代入sizeof(n), x代入sizeof(int)就得到
C. (sizeof(n)+(sizeof(int)-1)) & ~(sizeof(int)-1)
這個解釋是不是老太婆的纏腳布又臭又長?這是為什麼我沒在該篇文章
說明的原因。
_INTSIZEOF(n) 目的是要得到參數n無條件進位取sizeof(int)的倍數。
為什麼是無條件進位取sizeof(int)的倍數?因為這是一個較通用版本的
macro,一般的編譯器的定的int 型態的大小和堆疊存取的單位是相同的
(但不是絕對的,所以才又有特殊版本)

REF:http://ehome.hifly.to/showthread.php?s=&threadid=329

2008年3月2日 星期日

diff 與 patch

使用 diff 來產生新舊兩個 source tree(source code directory tree) 的差異性列表有助於比較前後的差異(修改、增減),另外還可以提供較精簡的源碼更新,後者就需要 patch 這支工具配合。

我習慣用下面的命令來產生 diff 檔:
diff -ruN DirA DirB > xx.diff

上述產生的 xx.diff 若是由其他人拿到要更新(同步)源碼的話, 只需要切換到產生 diff 的同目錄(可以看到 DirA 的那一層)再下: patch -p0 <> 即可。或者像我的話比較喜歡切換到 DirA 目錄下 patch -p1 < ../xx.diff 這樣較不會有混淆的狀況。

至於 diff 與 patch 的選項請自行參考說明文件。若是在 M$ OS 下,建議安裝 cygwin,它可以說是讓你在 M$ OS 下具有眾多 Linux 工具的最佳解決方案。

REF:http://wadefs.blogspot.com/2007/05/diff-patch.html