在編譯程式時,有時會需要Linux kernel header。除了用套件管理程式下載外,也可自己去下載Linux Kernel Source下來,透過下面指令安裝到指定的目錄下。
解壓縮完成後:
# make ARCH=$ARCH headers_check
# make ARCH=$ARCG INSTALL_HDR_PATH=$HEADER_DIR headers_install
$ARCH為處理器的架構平台,如ppc, arm等。
$HEADER_DIR為Header欲安裝的目的資料夾所在。
2010年6月18日 星期五
2010年4月18日 星期日
mmap
Mapped memory允許不同的Process透過Shared file來溝通,mmap()可以將檔案mapping到 process's address space中,好處是可以加速檔案的存取。
相關的函式:
#include <sys/mman.h>
void * mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off);
將檔案內容對應到記憶體
addr: 指定記憶體的起始位址,若為NULL,Linux會自動選擇一個可用的位址。
len: 對應的檔案的大小(byte)
prot: 記體體的存取權限,以下常數OR
PROT_READ - 可讀取
PROT_WRITE - 可寫入
PROT_EXEC - 可執行
PROT_NONE - 不可存取
flags :記憶體區段內容的修改方式
MAP_FIXED - 記憶體位址必須是指定的address
MAP_PRIVATE - 修改不會寫回原檔案
MAP_SHARED - 修改會反應到原檔案
int msync(void *addr, size_t len, int flags);
讓記憶體區段被修改的內容,寫回到對應該的檔案中
addr: 記憶體的起始位址
len: 記憶體區段的大小
flags: 更新方式
MS_ASYNC - 非同步寫入,不需馬上寫入
MS_SYNC - 同步寫入,馬上寫入
MS_INVALIDATE - 重新從檔案取得最新的資料
int munmap(void *addr, size_t len);
釋放記憶體區段
範例可參考此網頁
相關的函式:
#include <sys/mman.h>
void * mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off);
將檔案內容對應到記憶體
addr: 指定記憶體的起始位址,若為NULL,Linux會自動選擇一個可用的位址。
len: 對應的檔案的大小(byte)
prot: 記體體的存取權限,以下常數OR
PROT_READ - 可讀取
PROT_WRITE - 可寫入
PROT_EXEC - 可執行
PROT_NONE - 不可存取
flags :記憶體區段內容的修改方式
MAP_FIXED - 記憶體位址必須是指定的address
MAP_PRIVATE - 修改不會寫回原檔案
MAP_SHARED - 修改會反應到原檔案
int msync(void *addr, size_t len, int flags);
讓記憶體區段被修改的內容,寫回到對應該的檔案中
addr: 記憶體的起始位址
len: 記憶體區段的大小
flags: 更新方式
MS_ASYNC - 非同步寫入,不需馬上寫入
MS_SYNC - 同步寫入,馬上寫入
MS_INVALIDATE - 重新從檔案取得最新的資料
int munmap(void *addr, size_t len);
釋放記憶體區段
範例可參考此網頁
2010年3月17日 星期三
大量改檔名
若同一個資料夾裡,要用同樣的規則修改檔名,如所有為.dat副檔名要更名為.txt,可以寫一個簡單的shell script來完成。
先了解變數替換的方法
${var%word} - 由var變數內容的後端,向前刪除符合word關鍵字(最短部份)
${var%%word} - 由var變數內容的後端,向前刪除符合word關鍵字(最長份)
${var#word} - 由var變數內容的前端,向後刪除符合word關鍵字(最短部份)
${var##word} - 由var變數內容的前端,向後刪除符合word關鍵字(最長部份)
舉例:
變數$abc = howard, john, tom
# echo ${abc%,*}
howard, john
# echo ${abc%%,*}
howard
重新命名範例:將附檔名dat改為txt
先了解變數替換的方法
${var%word} - 由var變數內容的後端,向前刪除符合word關鍵字(最短部份)
${var%%word} - 由var變數內容的後端,向前刪除符合word關鍵字(最長份)
${var#word} - 由var變數內容的前端,向後刪除符合word關鍵字(最短部份)
${var##word} - 由var變數內容的前端,向後刪除符合word關鍵字(最長部份)
舉例:
變數$abc = howard, john, tom
# echo ${abc%,*}
howard, john
# echo ${abc%%,*}
howard
重新命名範例:將附檔名dat改為txt
#/bin/bash
for i in *.dat
do
mv $i "${i%dat}txt"
done
2010年3月7日 星期日
命令執行
在Shell Script常常會需要抓取或是儲存執行某個指令的結果。舊式的寫法是用反引號`cmd`,要注意的一點就是符號不是單引號(')。而新式的寫法是採用$(cmd)。
舊式:
echo The current date is `date`
新式
echo The current date is $(date)
舊式:
echo The current date is `date`
新式
echo The current date is $(date)
2010年1月3日 星期日
Daemon Tutorial
參考一份文件,介紹寫Daemon程式所需要的基本步驟:
1. Fork off the parent process
利用fork()脫離父程序,成為init的子程序
2. Change file mode mask
利用umask()控制Daemon所建立的檔案權限
3. Open any logs for writing
可透過寫檔或是syslog來記錄執行的過程
4. Create a unique Session ID
利用setsid()建立新的session並脫離tty
5. Change the current working directory to a safe place
利用chdir()來改變工作目錄(用意不太清楚)
6. Close standard file descriptors
因為Daemon不會使用terminal,所以關閉不必要的descriptors
7. Enter actual daemon code
Daemon所要執行的程式
程式碼架構可參考此網站
1. Fork off the parent process
利用fork()脫離父程序,成為init的子程序
2. Change file mode mask
利用umask()控制Daemon所建立的檔案權限
3. Open any logs for writing
可透過寫檔或是syslog來記錄執行的過程
4. Create a unique Session ID
利用setsid()建立新的session並脫離tty
5. Change the current working directory to a safe place
利用chdir()來改變工作目錄(用意不太清楚)
6. Close standard file descriptors
因為Daemon不會使用terminal,所以關閉不必要的descriptors
7. Enter actual daemon code
Daemon所要執行的程式
程式碼架構可參考此網站
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <syslog.h>
#include <sys/types.h>
#include <sys/stat.h>
#define DAEMON_NAME "MyDaemon"
int main(int argc, char** argv)
{
pid_t pid, sid;
// Change file mode mask
umask(0);
// Open logs for writing
openlog(DAEMON_NAME, LOG_CONS | LOG_NDELAY | LOG_PID, LOG_USER);
syslog(LOG_NOTICE, "%s daemon started", DAEMON_NAME);
pid = fork();
if(pid < 0) {
syslog(LOG_ERR, "Fail to fork a process");
exit(EXIT_FAILURE);
}
// Fork off the parent process
if(pid > 0) {
exit(EXIT_SUCCESS);
}
// Create a unique Session ID
sid = setsid();
if(sid < 0) {
syslog(LOG_ERR, "Fail to create a new Session ID");
exit(EXIT_FAILURE);
}
// Change the current working directory
if((chdir("/") < 0)) {
syslog(LOG_ERR, "Fail to change the current working directory");
exit(EXIT_FAILURE);
}
// Close out the standard file descriptiors
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
//******************************************************************
// Insert the daemon process
//******************************************************************
exit(EXIT_SUCCESS);
}
2009年12月12日 星期六
Pipe
當兩個不同的Process要溝通時,我們可以用pipe來達成。簡單來說,pipe就像是一條水管,連接兩個Process,其中一端寫入資料到水管,另一端便可從水管中讀出此資料。
建立pipe:
#include <unistd.h>
int pipe(int pipefd[2]);
呼叫pipe()來建立pipe,其參數int pipefd[2]是用來回傳兩個file descriptors,pipefd[0]代表的是pipe的讀取端,pipefd[1]則是pipe的寫入端。
簡單範例:
接下來就將單一Process擴展到不同的Process,寫出ls | wc -l,也就是計算當前目錄下有幾個檔案。
先利用fork產生Child Process,再叫用execlp()執行外部指令。
由於fork會使pipefd[0], pipefd[1]產生兩份,記得把不必要的Descriptor關閉,可避免不當的操作。
比較需要注意的便是dup2()的用法,dup2(pipefd[0], 0)可以把它想成複製pipefd[0]且當作是標準輸入(stdin),如此wc -l從stdin讀資料就會從pipe中讀取。
可參考此網頁的說明,便能明白dup2()的用意。
建立pipe:
#include <unistd.h>
int pipe(int pipefd[2]);
呼叫pipe()來建立pipe,其參數int pipefd[2]是用來回傳兩個file descriptors,pipefd[0]代表的是pipe的讀取端,pipefd[1]則是pipe的寫入端。
簡單範例:
#include <stdio.h>
#include <string.h>
int main() {
int pipefd[2];
pipe(pipefd);
char writeBuf[] = "Hello pipe!";
write(pipefd[1], writeBuf, strlen(writeBuf));
char readBuf[20];
int n = read(pipefd[0], readBuf, 20);
readBuf[n] = 0;
printf("%s\n", readBuf);
return 0;
}
接下來就將單一Process擴展到不同的Process,寫出ls | wc -l,也就是計算當前目錄下有幾個檔案。
先利用fork產生Child Process,再叫用execlp()執行外部指令。
#include <stdio.h>
#include <unistd.h>
int main() {
int pipefd[2];
pipe(pipefd);
pid_t pid = fork();
if(pid != 0) {
close(pipefd[1]);
dup2(pipefd[0], 0);
close(pipefd[0]);
execlp("wc", "wc", "-l", NULL);
}
else {
close(pipefd[0]);
dup2(pipefd[1], 1);
close(pipefd[1]);
execlp("ls", "ls", NULL);
}
return 0;
}
由於fork會使pipefd[0], pipefd[1]產生兩份,記得把不必要的Descriptor關閉,可避免不當的操作。
比較需要注意的便是dup2()的用法,dup2(pipefd[0], 0)可以把它想成複製pipefd[0]且當作是標準輸入(stdin),如此wc -l從stdin讀資料就會從pipe中讀取。
可參考此網頁的說明,便能明白dup2()的用意。
訂閱:
文章 (Atom)