顯示具有 programming 標籤的文章。 顯示所有文章
顯示具有 programming 標籤的文章。 顯示所有文章

2011年12月13日 星期二

Linux kernel內讀寫檔案

在driver裡面,我們有時需要留一些資訊在磁碟上讓userspace作溝通,因此需要從kernel上直接寫入檔案。

相關API程式碼如下:

void InitKernelEnv(void){ 
oldfs = get_fs();
set_fs(KERNEL_DS);
}

void DinitKernelEnv(){
set_fs(oldfs);
}

struct file *OpenFile(char *path,int flag,int mode){
struct file *fp;

fp=filp_open(path, flag, 0);
if (fp) return fp;
else return NULL;
}

int WriteFile(struct file *fp,char *buf,int readlen) {
if (fp->f_op && fp->f_op->read)
return fp->f_op->write(fp,buf,readlen, &fp->f_pos);
else
return -1;
}

int ReadFile(struct file *fp,char *buf,int readlen)
{
if (fp->f_op && fp->f_op->read)
return fp->f_op->read(fp,buf,readlen, &fp->f_pos);
else
return -1;
}

int CloseFile(struct file *fp) {
filp_close(fp,NULL);
return 0;
}

而使用方法請參考下面這個範例:

void test(){
char read_buf[2048] = "";
char write_buf[2048] = "";
struct file *fp;

InitKernelEnv();

//read file
fp = OpenFile(WPS_STA_LIST_FILE, O_RDONLY | O_CREAT, 0);
if(fp != NULL){
ReadFile(fp, read_buf, sizeof(read_buf));
}

CloseFile(fp);


//write to file
fp = OpenFile(WPS_STA_LIST_FILE, O_CREAT | O_WRONLY, 0);
if (fp!= NULL) {
WriteFile(fp, write_buf, sizeof(write_buf));
}

CloseFile(fp);

DinitKernelEnv();

}

參考資料:
[1] 請問內核中讀寫配置文件的源碼在哪個目錄的哪個文件中
[2] Reading file in kernel-簡單但實用

Linux kernel內取得時間

在kernel裡面,沒有辦法使用time(0)取得時間,但是我們可以利用do_gettimeofday()方式將時間取出。

//預先引入標頭檔
#include <linux/time.h>

...

//取得時間
struct timeval tv1;
do_gettimeofday(&tv1);

經由tv內部的tv_sec就可以取得目前系統時間的秒數了。


參考資料:
[1] linux kernel时间
[2] 时间处理函数 | do_gettimeofday() -- 获取当前系统时间

2010年12月26日 星期日

FileSystemWatcher and network device in C#

在C#中,對於檔案的監聽,提供了一個好用的API,即是FileSystemWatcher。他的語法也非常簡單,使用方法如下。

FileSystemWatcher watch = new FileSystemWatcher();
watch.Path = @"c:\";
watch.Changed += new FileSystemEventHandler(myFileWatchEvent);
watch.EnableRaisingEvents = true;

然後再寫一個myFileWatchEvent做目錄下檔案有變動時的對應事件。

private void AppFileWatchEvent(object sender, FileSystemEventArgs e) {
    FileInfo fi = new FileInfo(e.FullPath);
    if (fi.Name.CompareTo("test.txt") == 0) {
        //file change
    }
}

這樣一來,當目錄下的test.txt有任何更動時,就會觸發事件。

然而,FileSystemWatcher有個致命的缺點就是,他無法在網路磁碟機下正常運作。如果檔案在網路磁碟機下,由自己對檔案作改動,FileSystemWatcher是可以偵測到的。但如果是被其他人改動,除非我對該目錄手動作一個refresh動作,不然FileSystemWatcher是一點反應也沒有的。

這時候就要用老方法去監看檔案改變了。這裡是用定期看檔案日期有沒有做改變。

DateTime lastModifyTime = DateTime.MinValue;

private void DoFileChange(){
    FileInfo fw = new FileInfo(@"C:\test.txt");
    if (fw.Exists) {
        if(lastModifyTime == DateTime.MinValue){
            lastModifyTime = File.GetLastWriteTime(fw.FullName);
        }

        DateTime currentModifyTime = File.GetLastWriteTime(fw.FullName);

        if (lastModifyTime < currentModifyTime) {
            //File change   
        }
        lastModifyTime = currentModifyTime;
    }
}

然後用個while迴圈包起來。

private void DoFileChangeLoop(){
    while (true) {
        DoFileChange();
        Thread.Sleep(1000);
    }
}

當然,你必須將DoFileChangeLoop放在thread裡面。

實際執行下來,耗費的系統資源還蠻少的,在可以接受的範圍之內。

GUI Thread on C#

在C#中,一般情況下,控制GUI元件時,必須要用main thread去控制。然而我們常常將運算丟至一個新的thread中,然後在運算時更新GUI的狀態。這時例外就會警告你不能這樣做。MSDN提供了delegate解法去做,但我覺得麻煩,也不夠直覺。後來參考了這裡,是使用SynchronizationContext,發現還挺好用的。使用方如下。

首先在GUI class範疇下宣告SynchronizationContext。

public partial class A:Form{
    SynchronizationContext mainSynchronizationContext;
}

接著在constructor上面,將SynchronizationContext做指定。這樣SynchronizationContext就可以抓得到現在的執行緒。

public partial class A:Form{
    public A(){
        mainSynchronizationContext = SynchronizationContext.Current;
    }
}

然後寫一個方法,負責執行GUI更新動作。label1在這裡是一個Lebel類別

public void InvokeGUI(string str) {
    mainSynchronizationContext.Post
        (
        new SendOrPostCallback
            (
            (obj)
            =>
            {
               label1.Text=(String)obj;
               
            }
            )
            ,
            str
       );
}

其中mainSynchronizationContext.Post,是非同步處理,指的是不會等待GUI就進行下一步驟。如果使用mainSynchronizationContext.Send的話,則是進行同步處理。當GUI真正動作完成才會做返回動作。script則是傳入的引數。

然後在你的thread運算時呼叫這個function,便不會拋出例外訊息了。

參考資料:
[1] (筆記) 跨執行緒存取控制項 (WPF、WinForm 通用)
[2] 深入线程,实现自定义的SynchronizationContext

第[2]有詳細說明SynchronizationContext的原理,推薦可以看看。

2009年9月18日 星期五

C#獲得繪圖字串的寬度

在繪圖字串時,因為TrueType的關係,在畫面上每個字的寬度會呈現不一樣的寬度。如果自己要對畫面上版面作控制,很容易無法掌握到寬度。

網路上有人針對這問題提出解答。就是利用MeasureString這個類別來完成。MeasureString能夠回傳相近似的寬度值,下面這些範例可以幫助理解。如果需要比較精確的值,那麼你應該使用Graphic.MeasureCharacterRamges。以下是範例程式。

Graphics g = e.Graphics;
string s1 = "init";
string s2 = "wimp";
string s3 = "initwimp";
StringFormat format = new StringFormat();
format.SetMeasurableCharacterRanges(new CharacterRange[]{new
CharacterRange(0, s1.Length)});
Region[] r = g.MeasureCharacterRanges(s1, this.Font, new Rectangle(0, 0,
1000, 1000), format);
RectangleF rect = r[0].GetBounds(g);
// using MeasureCharacterRanges
g.DrawString(s1, this.Font, SystemBrushes.ControlText, 0, 0);
g.DrawString(s2, this.Font, SystemBrushes.ControlText, rect.Width, 0);
// the assmbled string
g.DrawString(s3, this.Font, SystemBrushes.ControlText, 0, 20);
// using MeasureString
SizeF sf = g.MeasureString(s1, this.Font);
g.DrawString(s1, this.Font, SystemBrushes.ControlText, 0, 40);
g.DrawString(s2, this.Font, SystemBrushes.ControlText, sf.Width, 40);

參考資料及程式碼來源:
[1] Get actual text width.

2009年9月15日 星期二

C#利用AxWindowsMediaPlayer播放mp3

使用AxWindowsMediaPlayer好處是利用內建的wmp播放器,可以免掉很多格式的問題。對於像我這樣的懶人,這方法是再好也不過了。使用方式就是把對應COM物件加入自己程式中,再進行呼叫就可以了。

步驟如下:

Step1. AxWindowsMediaPlayer只能依附在Form或是相關GUI控件下,所以首先要務就是產生一個Form物件或是UserControl物件。

Step 2. 接著下一步驟就是將這個COM物件加在自己的調色盤中嚕。

隨便在工具箱上按右鍵->選擇項目。
image 

接著會開啟工具箱選項,切換到COM頁面,選擇Windows Media Player項目。
image

很幸運地,會在工具箱看到Windows Media Player組件啦,把它拖進去你的Form中就可以了。
image 

Step 3. 接著是程式碼的撰寫。拖進去COM物件的預設名稱是axWindowsMediaPlayer1,不喜歡可以自己改。來個最簡單的教學吧!

-要播放某個mp3檔案
axWindowsMediaPlayer1.URL = "C:\\aaa.mp3";
axWindowsMediaPlayer1.Ctlcontrols.play();

-要停止播放
axWindowsMediaPlayer1.Ctlcontrols.stop();

-要暫停播放
axWindowsMediaPlayer1.Ctlcontrols.pause();

此外還有許多用法,可以去參考API。

參考資料:
[1] Play a mp3 sound using MediaPlayer in C#
[2] AxWMPLib.AxWindowsMediaPlayer 属性

2008年11月23日 星期日

JTablet

在java環境中若要寫手寫觸控的程式,在觸控方面最爛的方法是自己寫對應的滑鼠事件做為函式庫,對於一些感壓的偵測可能就沒輒了。其實這裡有現成的套件"JTablet"可以幫助開發程式,提供了手寫板所需要的功能。

使用方法為將jar檔加入自己的開發環境中即可。

http://sketchstudio.cellosoft.com/

image

2008年10月14日 星期二

An Online Handwritten System of Music Score

這玩意是我的論文題目。是一個手寫樂譜辨識系統。透過與平常手寫樂譜方法一筆一筆劃進行辨識,除此之外還針對細節作了許多的實作。

論文可以在全國碩博士論文裡面找到。簡單的說明與DEMO下載在這裡的實驗室網頁可以看到。

恩,有疑問可以提出,雖然說軟體已經算是停止開發了。

2008年10月11日 星期六

人臉比對的應用

這是我無聊時想到的關於人臉的應用。

首先需要兩個技術的配合。第一是人臉偵測技術,表示可以從照片中找出人臉的"位置"。第二是人臉辨識技術,表示可以辨識誰是誰。

搭配應用是這樣的,叫作"我在哪裡"。大意是我可能會出現在別人拍的照片中,或許我曾偶然出現在何時何地偶然被拍到。我們可以從使用者上傳的照片建立資料庫,然後運用人臉偵測技術把人臉刮出來,再利用辨識技術辨識出每張人臉。

這項應用也可以用在影片上,不過我想光是照片可能運算量就很大了,又要考慮到技術的成熟度,恩...很期待有人做出來,哈。

這項應用有趣度比較大啦~:)。

2008年9月23日 星期二

字串比對演算法

Exact string matching algorithms
http://www-igm.univ-mlv.fr/~lecroq/string/index.html

字串比對在資訊領域中常常用到,像是把問題化作兩條字串去做相似度的評比來求得近似的答案。這網頁中如列了許多種演算法,並有applet輔助說明。

演算法列表如下:

Brute Force algorithm
Deterministic Finite Automaton algorithm
Karp-Rabin algorithm
Shift Or algorithm
Morris-Pratt algorithm
Knuth-Morris-Pratt algorithm
Simon algorithm
Colussi algorithm
Galil-Giancarlo algorithm
Apostolico-Crochemore algorithm
Not So Naive algorithm
Boyer-Moore algorithm
Turbo BM algorithm
Apostolico-Giancarlo algorithm
Reverse Colussi algorithm
Horspool algorithm
Quick Search algorithm
Tuned Boyer-Moore algorithm
Zhu-Takaoka algorithm
Berry-Ravindran algorithm
Smith algorithm
Raita algorithm
Reverse Factor algorithm
Turbo Reverse Factor algorithm
Forward Dawg Matching algorithm
Backward Nondeterministic Dawg Matching algorithm
Backward Oracle Matching algorithm
Galil-Seiferas algorithm
Two Way algorithm
String Matching on Ordered Alphabets algorithm
Optimal Mismatch algorithm
Maximal Shift algorithm
Skip Search algorithm
KMP Skip Search algorithm
Alpha Skip Search algorithm

老實說,我還很弱,還沒看懂大部分,有空閒再來研究研究。

2008年8月9日 星期六

C# 控制螢幕開關

這裡可以由兩篇文章得知如何控制開、關和待命。

[1] Complete guide on How to turn a monitor on/off/standby
http://www.codeproject.com/KB/cs/Monitor_management_guide.aspx
[2] C# - 紀錄使用者視窗大小與位置、應用程式預設值
http://blog.roodo.com/chhuang/archives/3147437.html

為了使用方便,我將這些功能包裝起來成為一個簡單的class,程式碼在這裡。

使用範例:

MonitorControl mc = new MonitorControl();
mc.SetOff();

2008年7月3日 星期四

Java 讀入命令提示列字元

這是一段非常短的程式碼,但是還蠻常用到的。

讀入方法如下,取得結果為一字串。

String str=null;
BufferedReader buf=null;
buf=new BufferedReader(new InputStreamReader(System.in));
 

2008年6月27日 星期五

C# 繪製圓角矩形

當我們在利用C#進行2D繪圖的時候,最常用到DrawXXX的方式(XXX為自行帶入)。Draw具有許多圖形的繪製,像是DrawString、DrawRetangle等等。有時候我們需要繪製圓角矩形,卻發現沒有DrawRoundRetangle這類方法可以呼叫。

經過搜尋後,我發現網路上有個畫圓角矩形不錯的fuction(來源我有點不太記得了)。程式碼位置在這裡

下面是該function的開頭。只要傳入左上角x,y值和寬跟高,另外在加上圓角的程度。

private GraphicsPath DrawRoundRect(float x, float y, float width, float height, float cornerRadius)

下圖是經過繪製後的結果,粉紅色部分就是圓角矩形範例。image

2008年2月28日 星期四

C#用匿名方式使用Thread

一般看到C# Thread的範例是

Thread thread=new Thread(Do);
thread.Start();

代表的是將Do這function用Thread方式跑。而Do通常是一個無傳入引數的funciton。這裡就產生一個問題了,如果要傳入一個以上的引數,就不能用這種方式執行了。

在java中,Thread可以用匿名方式(Anonymous)啟動,範例如下:

Thread thread=new Thread(){
public void run(){
//Do something, like function f(x,y)
}};
thread.start();

其實在C#中也同樣有這樣的機制。寫的方式略與java不太相同。方法如下:

Thread thread=new Thread(delegate(){
//Do something, like function f(x,y)
});
thread.Start();

這樣一來,就可以隨心所欲在任何地方啟動一個新Thread了。

參考資料:
[1]C# Anonymous in depth http://bartdesmet.net/blogs/bart/archive/2006/09/10/4409.aspx
[2]Creating threads with inner classes http://java.poac.ac.cn/codeopen/jiaocheng/java2s/Code/Java/Threads/Creatingthreadswithinnerclasses.htm