?? linux.txt
字號:
Linux系統(tǒng)下的C語言開發(fā)都需要學(xué)些什么
2007-11-07 10:21作者:佚名出處:論壇整理責(zé)任編輯:方舟 一、工具的使用
1、學(xué)會使用vim/emacs,vim/emacs是linux下最常用的源碼編輯具,不光要學(xué)會用它們編輯源碼,還要學(xué)會用它們進(jìn)行查找、定位、替換等。新手的話推薦使用vim,這也是我目前使用的文本編輯器。
2、學(xué)會makefile文件的編寫規(guī)則,并結(jié)合使用工具aclocal、autoconf和automake生成makefile文件。
3、掌握gcc和gdb的基本用法。掌握gcc的用法對于構(gòu)建一個軟件包很有益處,當(dāng)軟件包包含的文件比較多的時候,你還能用gcc把它手動編譯出來,你就會對軟件包中各個文件間的依賴關(guān)系有一個清晰的了解。
4、掌握svn/cvs的基本用法。這是linux,也是開源社區(qū)最常用的版本管理系統(tǒng)。可以去試著參加sourceforge上的一些開源項目。
二、linux/unix系統(tǒng)調(diào)用與標(biāo)準(zhǔn)C庫
系統(tǒng)調(diào)用應(yīng)用軟件與操作系統(tǒng)的接口,其重要性自然不用說,一定要掌握。推薦學(xué)習(xí)資料為steven先生的UNIX環(huán)境高級編程(簡稱APUE)。
三、庫的學(xué)習(xí)
無論是在哪個平臺做軟件開發(fā),對于庫的學(xué)習(xí)都很重要,linux下的開發(fā)庫很多,我主要介紹一下我常常用到的一些庫。
1、glib庫
glib 庫是gtk+和gnome的基礎(chǔ)庫,并具是跨平臺的,在linux、unix和windows下都可以用。glib庫對于linux平臺開發(fā)的影響就像 MFC對windows平臺開發(fā)的影響一樣,很多開源項目都大量的使用了glib庫,包括gimp、gnome、gaim、evolution和 linux下的集群軟件heartbeat.因為glib庫自帶有基本的數(shù)據(jù)結(jié)構(gòu)實現(xiàn),所以在學(xué)習(xí)glib庫的時候可以順便學(xué)習(xí)一下基本的數(shù)據(jù)結(jié)構(gòu)(包括鏈表、樹、隊列和hash表)。
2、libxml庫
libxml是linux平臺下解析XML文件的一個基礎(chǔ)庫,現(xiàn)在很多實用軟件都用XML格式的配置文件,所以也有必要學(xué)習(xí)一下。
3、readline庫
readline 庫是bash shell用的庫,如果要開發(fā)命令行程序,那么使用readline庫可以減少很多工作量,比如bash里的命令行自動補(bǔ)全,在readline里就已經(jīng)有實現(xiàn),當(dāng)然你也可以用自己的實現(xiàn)替代庫的行為。readline庫有很多網(wǎng)站介紹的,只要google一下readline就可以找到一堆了。
4、curses庫
curses 庫以前是vi程序的一部分,后來從vi里提取出來成為一個獨立的庫。curses庫對于編寫終端相關(guān)的程序特別有用,比如要在終端某一行某一列定位輸出,改變終端字體的顏色和終端模式。linux下的curses庫用的是GNU實現(xiàn)的ncurses(new curses的意思)。
5、gtk+和KDE庫
這兩個庫是開發(fā)GUI應(yīng)用程序的基礎(chǔ)庫,現(xiàn)在linux下的大部份GUI程序都是基于這兩個庫開發(fā)的,對于它們 的學(xué)習(xí)也是很有必要的。
四、網(wǎng)絡(luò)的學(xué)習(xí)
網(wǎng)絡(luò)這個東西太寬了,推薦學(xué)習(xí)資料steven先生的UNIX網(wǎng)絡(luò)編程(簡稱UNP)和TCP/IP協(xié)議詳解,更進(jìn)一步的話可以學(xué)習(xí)使用libnet編寫網(wǎng)絡(luò)程序。
在Linux平臺下對文件編程可以使用兩類函數(shù):(1)Linux操作系統(tǒng)文件API;(2)C語言I/O庫函數(shù)。 前者依賴于Linux系統(tǒng)調(diào)用,后者實際上與操作系統(tǒng)是獨立的,因為在任何操作系統(tǒng)下,使用C語言I/O庫函數(shù)操作文件的方法都是相同的。本章將對這兩種方法進(jìn)行實例講解。
2.Linux文件API
Linux的文件操作API涉及到創(chuàng)建、打開、讀寫和關(guān)閉文件。
創(chuàng)建
int creat(const char *filename, mode_t mode);
參數(shù)mode指定新建文件的存取權(quán)限,它同umask一起決定文件的最終權(quán)限(mode&umask),其中umask代表了文件在創(chuàng)建時需要去掉的一些存取權(quán)限。umask可通過系統(tǒng)調(diào)用umask()來改變:
int umask(int newmask);
該調(diào)用將umask設(shè)置為newmask,然后返回舊的umask,它只影響讀、寫和執(zhí)行權(quán)限。
打開
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
open函數(shù)有兩個形式,其中pathname是我們要打開的文件名(包含路徑名稱,缺省是認(rèn)為在當(dāng)前路徑下面),flags可以去下面的一個值或者是幾個值的組合:
標(biāo)志 含義
O_RDONLY 以只讀的方式打開文件
O_WRONLY 以只寫的方式打開文件
O_RDWR 以讀寫的方式打開文件
O_APPEND 以追加的方式打開文件
O_CREAT 創(chuàng)建一個文件
O_EXEC 如果使用了O_CREAT而且文件已經(jīng)存在,就會發(fā)生一個錯誤
O_NOBLOCK 以非阻塞的方式打開一個文件
O_TRUNC 如果文件已經(jīng)存在,則刪除文件的內(nèi)容
O_RDONLY、O_WRONLY、O_RDWR三個標(biāo)志只能使用任意的一個。
如果使用了O_CREATE標(biāo)志,則使用的函數(shù)是int open(const char *pathname,int flags,mode_t mode); 這個時候我們還要指定mode標(biāo)志,用來表示文件的訪問權(quán)限。mode可以是以下情況的組合:
標(biāo)志 含義
S_IRUSR 用戶可以讀
S_IWUSR 用戶可以寫
S_IXUSR 用戶可以執(zhí)行
S_IRWXU 用戶可以讀、寫、執(zhí)行
S_IRGRP 組可以讀
S_IWGRP 組可以寫
S_IXGRP 組可以執(zhí)行
S_IRWXG 組可以讀寫執(zhí)行
S_IROTH 其他人可以讀
S_IWOTH 其他人可以寫
S_IXOTH 其他人可以執(zhí)行
S_IRWXO 其他人可以讀、寫、執(zhí)行
S_ISUID 設(shè)置用戶執(zhí)行ID
S_ISGID 設(shè)置組的執(zhí)行ID
除了可以通過上述宏進(jìn)行“或”邏輯產(chǎn)生標(biāo)志以外,我們也可以自己用數(shù)字來表示,Linux總共用5個數(shù)字來表示文件的各種權(quán)限:第一位表示設(shè)置用戶ID;第二位表示設(shè)置組ID;第三位表示用戶自己的權(quán)限位;第四位表示組的權(quán)限;最后一位表示其他人的權(quán)限。每個數(shù)字可以取1(執(zhí)行權(quán)限)、2(寫權(quán)限)、4(讀權(quán)限)、0(無)或者是這些值的和。例如,要創(chuàng)建一個用戶可讀、可寫、可執(zhí)行,但是組沒有權(quán)限,其他人可以讀、可以執(zhí)行的文件,并設(shè)置用戶ID位。那么,我們應(yīng)該使用的模式是1(設(shè)置用戶ID)、0(不設(shè)置組ID)、7(1+2+4,讀、寫、執(zhí)行)、0(沒有權(quán)限)、5(1+4,讀、執(zhí)行)即10705:
open("test", O_CREAT, 10705);
上述語句等價于:
open("test", O_CREAT, S_IRWXU | S_IROTH | S_IXOTH | S_ISUID );
如果文件打開成功,open函數(shù)會返回一個文件描述符,以后對該文件的所有操作就可以通過對這個文件描述符進(jìn)行操作來實現(xiàn)。
讀寫
在文件打開以后,我們才可對文件進(jìn)行讀寫了,Linux中提供文件讀寫的系統(tǒng)調(diào)用是read、write函數(shù):
int read(int fd, const void *buf, size_t length);
int write(int fd, const void *buf, size_t length);
其中參數(shù)buf為指向緩沖區(qū)的指針,length為緩沖區(qū)的大小(以字節(jié)為單位)。函數(shù)read()實現(xiàn)從文件描述符fd所指定的文件中讀取length個字節(jié)到buf所指向的緩沖區(qū)中,返回值為實際讀取的字節(jié)數(shù)。函數(shù)write實現(xiàn)將把length個字節(jié)從buf指向的緩沖區(qū)中寫到文件描述符fd所指向的文件中,返回值為實際寫入的字節(jié)數(shù)。
以O(shè)_CREAT為標(biāo)志的open實際上實現(xiàn)了文件創(chuàng)建的功能,因此,下面的函數(shù)等同creat()函數(shù):
int open(pathname, O_CREAT | O_WRONLY | O_TRUNC, mode);
定位
對于隨機(jī)文件,我們可以隨機(jī)的指定位置讀寫,使用如下函數(shù)進(jìn)行定位:
int lseek(int fd, offset_t offset, int whence);
lseek()將文件讀寫指針相對whence移動offset個字節(jié)。操作成功時,返回文件指針相對于文件頭的位置。參數(shù)whence可使用下述值:
SEEK_SET:相對文件開頭
SEEK_CUR:相對文件讀寫指針的當(dāng)前位置
SEEK_END:相對文件末尾
offset可取負(fù)值,例如下述調(diào)用可將文件指針相對當(dāng)前位置向前移動5個字節(jié):
lseek(fd, -5, SEEK_CUR);
由于lseek函數(shù)的返回值為文件指針相對于文件頭的位置,因此下列調(diào)用的返回值就是文件的長度:
lseek(fd, 0, SEEK_END);
關(guān)閉
當(dāng)我們操作完成以后,我們要關(guān)閉文件了,只要調(diào)用close就可以了,其中fd是我們要關(guān)閉的文件描述符:
int close(int fd);
例程:編寫一個程序,在當(dāng)前目錄下創(chuàng)建用戶可讀寫文件“hello.txt”,在其中寫入“Hello, software weekly”,關(guān)閉該文件。再次打開該文件,讀取其中的內(nèi)容并輸出在屏幕上。
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#define LENGTH 100
main()
{
int fd, len;
char str[LENGTH];
fd = open("hello.txt", O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); /* 創(chuàng)建并打開文件 */
if (fd)
{
write(fd, "Hello, Software Weekly", strlen("Hello, software weekly")); /* 寫入 Hello, software weekly字符串 */
close(fd);
}
fd = open("hello.txt", O_RDWR);
len = read(fd, str, LENGTH); /* 讀取文件內(nèi)容 */
str[len] = '\0';
printf("%s\n", str);
close(fd);
}
編譯并運(yùn)行,執(zhí)行結(jié)果如下圖:
3.C語言庫函數(shù)
C庫函數(shù)的文件操作實際上是獨立于具體的操作系統(tǒng)平臺的,不管是在DOS、Windows、Linux還是在VxWorks中都是這些函數(shù):
創(chuàng)建和打開
FILE *fopen(const char *path, const char *mode);
fopen()實現(xiàn)打開指定文件filename,其中的mode為打開模式,C語言中支持的打開模式如下表:
標(biāo)志 含義
r, rb 以只讀方式打開
w, wb 以只寫方式打開。如果文件不存在,則創(chuàng)建該文件,否則文件被截斷
a, ab 以追加方式打開。如果文件不存在,則創(chuàng)建該文件
r+, r+b, rb+ 以讀寫方式打開
w+, w+b, wh+ 以讀寫方式打開。如果文件不存在時,創(chuàng)建新文件,否則文件被截斷
a+, a+b, ab+ 以讀和追加方式打開。如果文件不存在,創(chuàng)建新文件
其中b用于區(qū)分二進(jìn)制文件和文本文件,這一點在DOS、Windows系統(tǒng)中是有區(qū)分的,但Linux不區(qū)分二進(jìn)制文件和文本文件。
讀寫
C庫函數(shù)支持以字符、字符串等為單位,支持按照某中格式進(jìn)行文件的讀寫,這一組函數(shù)為:
int fgetc(FILE *stream);
int fputc(int c, FILE *stream);
char *fgets(char *s, int n, FILE *stream);
int fputs(const char *s, FILE *stream);
int fprintf(FILE *stream, const char *format, ...);
int fscanf (FILE *stream, const char *format, ...);
size_t fread(void *ptr, size_t size, size_t n, FILE *stream);
size_t fwrite (const void *ptr, size_t size, size_t n, FILE *stream);
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -