gnowledge network 這個網站會將 debian package (deb) 的相依性,以圖示的方式顯示出來,讓使用者可以更清楚了解到套件之間的關係,我隨便輸入一個 "gcin",它的 roadmap 真他媽的複雜XDD。以下是 vim-common 的 roadmap:
2009年1月10日 星期六
2009年1月7日 星期三
Linux PAM
PAM 全名為「Pluggable Authentication Module」,是用來做認証的模組。許多程式,如: login、rlogin、sshd、ftpd、su、passwd...等都有支援 PAM,當然你也可以利用 ldd 指令來查詢某程式是否支援 PAM。
##ReadMore##
##ReadMore##
linly@linly-laptop:~$ ldd /usr/bin/passwd ... libpam.so.0 => /lib/libpam.so.0 (0xb800f000) libpam_misc.so.0 => /lib/libpam_misc.so.0 (0xb800b000) ...PAM 有許多有趣的應用,例如:利用指紋辨識或臉部辨識登入電腦、限制某項服務的使用時間,資源,次數、設定密碼時檢查密碼強度等等。在陳柏菁的 PAM 認証模組 網頁中有詳細介紹 PAM 是什麼?該如何設定?在此就不加贅述,不過要提醒讀者幾件事情:
- 認証模組有堆疊特性:設定時可以使用多種認証方式。
- control flag 的先後次序:例如 sufficient 放在 required 之後來使用,那 sufficient 模組的成功與否就會被忽略。
- 要了解每種 control flags 的意義:例如 required 與 requisite 的差異。
gcc -fPIC -c pam_module.c gcc -shared -o pam_module.so pam_module.o -lpam sudo cp pam_module.so /usr/lib/
gcc -o pam_app pam_app.c -lpam -lpam_misc -lpam_module
- Hint:撰寫 pam application 時,需要做 pam_set_item,而 item type 不能使用 PAM_AUTHTOK 及 PAM_OLDAUTHTOK,所以就隨便設定一個。
- Hint:撰寫 pam module 時,需要引用
當中的 getspnam 函式來取得加密過的密碼,至於為什麼要自己寫一個 module,因為 PAM 模組的帳密認証方式只能先輸入帳號,等他確認有這個使用者,才會在要求輸入密碼,既然說要改變他的行為,模組只好自己寫。
2008年12月31日 星期三
mmap()
mmap 函式是用來將檔案映射到記憶體,video for linux two 就是透過這種方式,將 device memory mapping into user space,而 uvcvideo driver 會實作這個 file operation,來幫 camera application 建立 VMA 區段。mmap() 的原型如下:##ReadMore##
08048000-08049000 r-xp 00000000 08:06 606289 /home/linly/Sample/mmap_write
...
b7df2000-b7f4a000 r-xp 00000000 08:06 1497227 /lib/tls/i686/cmov/libc-2.8.90.so
...
b7f61000-b7f62000 -w-s 00000000 08:06 686791 /tmp/shared_file
...
b7f80000-b7f81000 rw-p 0001b000 08:06 1479875 /lib/ld-2.8.90.so
bff6c000-bff81000 rw-p bffeb000 00:00 0 [stack]
void *mmap(void *addr, size_t len, int prot,
int flags,int fildes, off_t off);
- addr:用來告知從哪個記憶體位址開始映射,不過通常是擺 NULL,直接給作業系統決定,否則還要考慮對齊問題(alignment)
- len:映射的大小
- prot:對此記憶體的操作限制,如:PROT_READ、PROT_WRITE、PROT_EXEC、PROT_NONE
- flags:對此記憶體的存取方式,如:MAP_SHARED、MAP_PRIVATE、MAP_FIXED,使用 MAP_SHARED 時,如果某一個行程有對 mmap 的記憶體做修改,那其他同樣有做 mmap 的行程會看到相同結果。(對同一個檔案)
- fildes:open file 所得到的 fd。
- off:指定檔案從哪裡開始對映
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#define FILE_LENGTH 0x400 /* 1024 */
int main(int argc, char *argv[])
{
int fd;
void *map_memory;
if(argc < 2) {
printf("Usage: ./a.out <string>\n");
return 1;
}
/*
* Open a file to be mapped.
* S_IRUSR: read permission, owner
* S_IWUSR: write permission, owner
*/
fd = open("/tmp/shared_file", O_RDWR | O_CREAT,
S_IRUSR | S_IWUSR);
lseek(fd, FILE_LENGTH-1, SEEK_SET);
write(fd, "", 1);
lseek(fd, 0, SEEK_SET);
/* Create map memory. */
map_memory = mmap(0, FILE_LENGTH,
PROT_WRITE, MAP_SHARED,
fd, 0);
close(fd);
/* Write to mapped memory. */
if(strlen(argv[1]) < FILE_LENGTH)
sprintf((char*)map_memory, "%s", argv[1]);
munmap(map_memory, FILE_LENGTH);
return 0;
}
這樣的作法還是可以將內容寫入檔案,而且速度比單純寫入檔案還要快,但似乎 mmap有大小的限制,因為我設定到 0x40000000,程式執行完後,系統變得怪怪的 =.=?。以下是該測試程式的 VMA 區段,位於 /proc/xxxx/maps,其中 xxxx 是 process id,可以在執行程式時輸入 &,如:./mmaptest input_string &。08048000-08049000 r-xp 00000000 08:06 606289 /home/linly/Sample/mmap_write
...
b7df2000-b7f4a000 r-xp 00000000 08:06 1497227 /lib/tls/i686/cmov/libc-2.8.90.so
...
b7f61000-b7f62000 -w-s 00000000 08:06 686791 /tmp/shared_file
...
b7f80000-b7f81000 rw-p 0001b000 08:06 1479875 /lib/ld-2.8.90.so
bff6c000-bff81000 rw-p bffeb000 00:00 0 [stack]
2008年12月17日 星期三
如何使用 GtkProgressBar
進度條(ProgressBar)是一個和使用者互動必備的元件,因為你必須讓使用者了解目前處理進度,若等不下去就可以趕緊取消。至於使用他的方式我覺得可以採取「Timer」或「Thread」。下面就以計時器的方式來介紹進度條的使用。但礙於程式太佔版面,所以只會顯示部份程式碼。
一個進度條的產生是透過 gtk_progress_bar_new,進度條的範圍是[0,1],且以浮點數儲存。如果要讀取或修改進度條的數值利用 gtk_progress_bar_set(get)_fraction。了解這些之後,咱們就來看看程式碼。
最後再介紹兩支和進度條相關的函式:
gtk_progress_bar_set_pulse_step(GTK_PROGRESS_BAR(progressbar),0.1);
gtk_progress_bar_pulse(GTK_PROGRESS_BAR(progressbar));
這兩支函式可以讓進度條內的東東左跑右跑,就是放入 Live CD,在 ubuntu 圖樣的那個畫面,進度條開始跑進度之前的行為。就如同以上的程式碼,每次以0.1的間隔在移動,移動完右邊,就移左邊;移動完左邊,就移動右邊。
一個進度條的產生是透過 gtk_progress_bar_new,進度條的範圍是[0,1],且以浮點數儲存。如果要讀取或修改進度條的數值利用 gtk_progress_bar_set(get)_fraction。了解這些之後,咱們就來看看程式碼。
/*
以下程式執行會產生一個主視窗+按鍵
當按下按鍵就建立另一個視窗+進度條
並且透過計時器每次增加0.01,直到1.0為止
*/
#include<gtk/gtk.h>
gdouble new_val;
guint timer_id = 0;
static gboolean flush_progressbar(gpointer progressbar)
{
new_val= gtk_progress_bar_get_fraction(GTK_PROGRESS_BAR(progressbar))+0.01;
if(new_val >= 1.0) new_val = 1.0;
gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progressbar), new_val);
if(new_val >= 1.0) {
/* 舊版是用 gtk_timeout_remove() */
g_source_remove(timer_id);
return FALSE;
}
return TRUE; // 如此計時器才會一直 work
}
static void create_window(GtkWidget *widget, gpointer window)
{
// 產生並初始化視窗
...
GtkWidget *progressbar;
progressbar = gtk_progress_bar_new();
gtk_layout_put(GTK_LAYOUT(layout), progressbar, 100, 200);
...
// 100毫秒執行一次
/* 舊版是用 gtk_timeout_add() */
timeId = g_timeout_add(100 , flush_progressbar, progressbar);
}
int main(int argc, char *argv[])
{
// window - 主視窗
// window_create_after - 按下按鍵後產生的視窗
GtkWidget *window;
GtkWidget *window_create_after;
GtkWidget *button;
gtk_set_locale();
gtk_init(&argc, &argv);
// 產生並初始化 window
// 產生並出使化 button、加到 window 中
// 註冊 clicked 事件用來產生 window_create_after
// 以及產生一個 timer
gtk_main();
return(0);
}
這裡要注意的有兩點:
- 不要計時器中加入 delay 的機制(如:sleep),因為會導致前一次沒處理完,下一次又開始處理(re-entrant routine),導致 stack overflow。
- 不要讓主程式(main process)去處理 progressbar 的值,因為只會看到最終完成的畫面,中間的遞增過程使用者看不到。會有這種結果其實也不難想像,由於主程式正在執行某個function call,即使你不斷地更新進度條的內容,這些 event handler 只能等到目前的程式執行完,控制權回到 caller (也許好幾層),才會去執行這些更新畫面的 handler。
最後再介紹兩支和進度條相關的函式:
gtk_progress_bar_set_pulse_step(GTK_PROGRESS_BAR(progressbar),0.1);
gtk_progress_bar_pulse(GTK_PROGRESS_BAR(progressbar));
這兩支函式可以讓進度條內的東東左跑右跑,就是放入 Live CD,在 ubuntu 圖樣的那個畫面,進度條開始跑進度之前的行為。就如同以上的程式碼,每次以0.1的間隔在移動,移動完右邊,就移左邊;移動完左邊,就移動右邊。
2008年12月12日 星期五
Video For Linux Two
這是最近一兩個禮拜 study 的主題:V4L2,是在 Linux 中用來擷取影像的 API,隨著你安裝作業系統,V4L2 就會一併裝上去,以下是自己製作的投影片,Enjoy it... : )
參考資料:http://v4l2spec.bytesex.org/spec-single/v4l2.html
參考資料:http://v4l2spec.bytesex.org/spec-single/v4l2.html
2008年12月7日 星期日
HP Pavilion DV7 安裝 Ubuntu 8.10 沒有音效
在公司的工作機是 HP Pavilion DV7 ,我在上面安裝 Vista Business 與 Ubuntu,想當然爾,Windows 的運作正常得很,不過進入 Ubuntu 時,登入畫面在正常情況下會發出「登登」兩聲,但我的卻是詭異的「登登登登......(聲音越來越小 囧)」,且登入後沒有聲音,這種奇妙的狀況當然要交給 Google 大神,以下修改 /etc/modprobe.d/alsa-base 這個檔案,重開機後即正常:
##ReadMore##
##ReadMore##
sudo vi /etc/modprobe.d/alsa-base參考網頁:http://www.ubuntu-tw.org/modules/newbb/viewtopic.php?viewmode=thread&topic_id=11933&forum=3&post_id=61152
在檔案最後加上 options snd-hda-intel enable_msi=1
CodeBlocks 設定值無法儲存
不知道為什麼,這次重灌 Ubuntu,竟然發生每次啟動 Codeblocks,都像"第一次"使用一樣,導致設定值都要重設,卻又儲存不了,Google了一下,發現原來它和 gcin 相衝(?),所以改了以下的設定檔,然後重開機就正常了:##ReadMore##
sudo gedit /etc/X11/xinit/xinput.d/gcin從來沒發生過的事情,這次竟然莫名其妙的發生了(攤)。
將 GTK_IM_MODULE=gcin 改成 GTK_IM_MODULE=xim
2008年10月17日 星期五
C++ STL 容器的建(解)構
最近複習 STL,使用時發現一個現象,這邊我以 vector 為例來描述:
##ReadMore##
Constructed
Destructed
Destructed
Destructed
Destructed
從輸出的結果我們可以發現,vector的建構子會先建構出一個 FOO 類別的實體,接著再將內容複製三份至容器中,所以 vector data(3); 這一行敘述相當於 FOO foo; vector data(3,foo); 。其實,C++ 容器都是以複製的方式來做建構,如:list、deque..,etc。不過搞不太懂是如何實作XD!有空再想想看好了。
##ReadMore##
#include <iostream>
#include <vector>
using namespace std;
struct Foo {
Foo() {
cout << "Constructed" << endl;
}
~Foo() {
cout << "Destructed" << endl;
}
};
int main() {
vector<Foo> data(3);
return 0;
}
跑出來的結果如下所示:Constructed
Destructed
Destructed
Destructed
Destructed
從輸出的結果我們可以發現,vector的建構子會先建構出一個 FOO 類別的實體,接著再將內容複製三份至容器中,所以 vector
2008年10月5日 星期日
如何讓束縛函式作用在自訂的函式物件中
束縛函式可以對雙元的函式物件作限制,共分為兩種:bind1st 與 bind2nd。例如:
original data: 58 25 13 96 11 47 68 33 86 35
changed data: 50 25 13 50 11 47 50 33 50 35
因此,只要繼承 binary_function,自訂的函式物件結構也能使用束縛函式。另外還有一個稱作否定函式,對象是單元的函式物件,所以只要自訂的函式物件結構去繼承 unary_function 即可。
less如果我想讓束縛函式限制我自訂的函式物件,該如何做?這時只要去繼承 binary_function 這個結構即可,我們可以稍微看一下他的長相:include/bits/stl_function.h<T>(a, b); // 比較 a 是否比 b 小 bind1st(less ##ReadMore##<T>(), 50); // 限制 a 為 50,比較 50 < b bind2nd(less<T>(), 90); // 限制 b 為 90,比較 a < b
template <class _Arg1, class _Arg2, class _Result>它是由三個樣板參數組成,前兩個為運算元(operand),第三個為回傳型別,所以以下實際舉個例子,定義一個繼承自 binary_function 的結構,名為 Less。struct binary_function { typedef _Arg1 first_argument_type; typedef _Arg2 second_argument_type; typedef _Result result_type; };
// 自訂函式物件的結構,並繼承自 binary_function template <class _Tp>接著透過 adjust 函式來使用束縛函式,並配合上面所定義的 Less 函式物件結構:& struct Less : public binary_function<_Tp, _Tp, bool> { bool operator() (const _Tp & __x, const _Tp __y) const { return __x < __y; } };
// 若資料小於門檻值,就直接調整成門檻值 template <class Iter, class Fn, class T>輸出結果:" void adjust( Iter itr1 , Iter itr2 , Fn fn, T threshold ) { for (; itr1 != itr2; ++itr1 ) { if (fn(*itr1)) *itr1 = threshold ; } } int main() { srand((unsigned)time(NULL)); int i; const int SIZE = 10; const int THRESHOLD = 50; vector<int> data1(SIZE); for (i = 0; i < SIZE; ++i) data1[i] = rand()%100+1; cout << " original data: << ; for (i = 0; i < SIZE; ++i) cout << data1[i] << ' '; cout " endl; adjust(data1.begin(), data1.end(), bind1st(Less<int>(), THRESHOLD), THRESHOLD); cout << " changed data: << ; for (i = 0; i < SIZE;data1[i]; ++i) cout << ' ' data1[i] << ; cout endl; return 0; }
original data: 58 25 13 96 11 47 68 33 86 35
changed data: 50 25 13 50 11 47 50 33 50 35
因此,只要繼承 binary_function,自訂的函式物件結構也能使用束縛函式。另外還有一個稱作否定函式,對象是單元的函式物件,所以只要自訂的函式物件結構去繼承 unary_function 即可。
2008年10月2日 星期四
TrueType 中的細明體、新細明體、與標楷體所造成文字破碎的情況
由於自己的論文,需要 pdf library 的輔助,來讀取該檔案格式,所以找來了 Xpdf 這個 open source 來使用,卻發現到當中文字使用微軟細明體、新細明體、或者是標楷體時,會發生文字破碎的清況...如下圖所示:( 我是在 Windows XP上面開發 )
訂閱:
文章 (Atom)

