時光飛逝,轉眼已經畢業快2年了,覺得自己學的東西多卻不精。對此深深的思考一下,覺得有必要連載unix環境編程文章,以此激勵自己學習。在此立貼為證,2天一篇博客從零開始闡述unix的環境編程。 參考書籍UNIX環境高級編程第三版 ...
時光飛逝,轉眼已經畢業快2年了,覺得自己學的東西多卻不精。對此深深的思考一下,覺得有必要連載unix環境編程文章,以此激勵自己學習。在此立貼為證,2天一篇博客從零開始闡述unix的環境編程。
參考書籍UNIX環境高級編程第三版
下一篇UNIX編程基礎下:http://www.cnblogs.com/smartxuchao/p/6658060.html
如上圖1.1描述的是一個UNIX的體繫結構。對於一個Linux的新手上圖描述就是幾個關鍵字。但對於一個Linux的高手來說,這個圖描述了太多的信息量了。
內核:從嚴格的意義上來說,可將操作系統理解成一個軟體,他控制電腦的硬體資源提供給應用程式運行的環境。其實Linux就是一個內核,它是GNU操作系統的內核。當然我們熟悉的MAC OSX也是GNU操作系統的內核。
系統調用:系統調用是內核對外提供服務一個介面,好比你要操作鍵盤。肯定有人會說這個知道我們可以通過API函數來操作鍵盤,你說的沒錯。但是要記住API函數也就是庫函數是建立在系統調用之上的。內核提供的系統調用數目非常有限,到2.6.23版本的內核也不過才達到僅僅325個,但是API函數有那麼多。
庫函數:就是一個滿足POSIX標準的函數集合
Shell:一類的特殊的軟體,它是命令解釋器。類比window下cmd,它也是通過系統調用方式與內核交互。我們可以通過strace 命令查看 shell命令的實現過程。如strace echo。
總結:系統調用是訪問內核的唯一手段,在驅動開發時候會更加深刻的理解系統調用。
登錄UNIX
我們登錄unix系統的時候,系統做了什麼呢?原來在我們輸入用戶名和密碼的時候,系統會在/etc/passwd查找匹配的用戶名和密碼
如上圖依次是用戶名:密碼(系統已將口令加密到另一個文件):數字用戶ID:數字組用戶ID:註釋碼:起始目錄:shell程式
總共有6個:號組成的7個欄位。哈哈現在明白你的登錄過程了吧,知道為什麼你的起始目錄在/root下了吧;
要註意的地方shell版本很多,要註意觀看自己的系統是什麼shell
目前比較流行的shell
1./bin/bash
2. /bin/sh
3. /bin/ksh
4. /bin/csh
5. /bin/tcsh
6. /bin/dash
我們可以通過如下命令來觀看我們正在運行的shell的版本
文件和目錄
- Unix系統都是從根目錄/擴展下來的
- 我們創建新目錄的時候都出創建2個文件名分別是.和..。.是指向當前目錄,..指向上級目錄
- 文件命名的時候不要出現/和空字元。斜杠是用來分割路徑名中各個文件的,空格符則是終止一個路徑名
下麵我們用C來實現 shell中 ls命令
#include <unistd.h> #include <dirent.h> #include <errno.h> #include <stdlib.h> #include <string.h> int main(int argc,char *argv[]) { DIR *dp;//目錄的描述符 struct dirent *dirp;//目錄內容的結構體 if(argc != 2) { printf("please input --help"); return -1; } if(strcmp(argv[1],"--help") == 0) { puts("-a, --all不隱藏任何以. 開始的項目\n \ -A, --almost-all 列出除. 及.. 以外的任何項目\n\ --author 與-l 同時使用時列出每個文件的作者\n\ -b, --escape 以八進位溢出序列表示不可列印的字元\n"); return 0; } if((dp = opendir(argv[1])) == NULL) perror("can not open %s",argv[1]);/判斷標準錯誤的類型 while((dirp = readdir(dp)) != NULL ) printf("%s\n",dirp->d_name); // printf("Hello world!\n"); return 0; }
我想根據運行結果很容易看出來我們的程式。
輸入和輸出
1、 文件描述符:通常是一個非負的整數,內核用以表示一個特定的進程正在訪問的文件。當內核打開一個現有的文件或創建一個新的文件時返回的一個描述符。在讀寫的時候可以使用這個描述符
2、 每當運行一個新的程式,所有shell都會為其打開3個描述符,即標準的輸入、標準的輸出、標準的錯誤。預設3個描述符都是指向終端的。好比我們運行任意一個c程式,如果出錯誤,你會在哪兒看到錯誤提示,對的我們都會在終端看到。同理標準的輸入和輸出都是在終端。
說的這肯定有疑問這終端可以修改麽當然可以的如下
使用標準的ls
可以看得出結果輸出在終端上
如何修改成 ls >2.txt,好吧終端上什麼也沒列印。結果輸出到了2.txt中了,cat 2.txt(打開2.txt文件)果然發現了ls命令的結果
程式和進程
1、程式是一個存儲在磁碟的目錄中的一個可執行文件。內核使用exec函數(7個exec中一個),將程式讀到記憶體並執行
2、程式執行的實例就是進程,每個進程都有一個id叫做pid
3、線程:一個進程通常只有一個任務線程在處理,如果對於一個多個問題的事情,可以使用多個線程去處理,事情將變得異常輕鬆。一個進程的線程共用同一地址空間,文件描述符,棧等。當然如何區分不同的線程,對,使用線程ID,線程ID只在進程中起作用。
下麵是應用程式如何使用exec函數來吊起其他的程式的執行,加深對內核運行程式的理解
#include <stdio.h> #include <unistd.h> #include <sys/wait.h> #include <string.h> int main() { char buf[10]; int i; pid_t pid; int status; printf("cmd:"); memset(buf,'\0',10); while(gets(buf)) { if((pid = fork()) < 0){ perror("fork creat error\n"); }else if(pid == 0){ if(execlp(buf,buf,(char *)0 ) < 0)//運行一個指定的程式 perror("execlp error\n"); exit(127); } if((pid = waitpid(pid,&status,0)) < 0) perror("wait pid error\n"); printf("cmd:"); } return 0; }
本文章為unix環境編程的基礎上,涉及到很多知識點都是很簡單的描述下,比如線程和進程都會在後期的文章細細的說到。下一遍博客問unix環境編程基礎下,繼續在巨集觀上描述unix系統。結合unix環境編程上下再展開將會涵蓋unix大多數內容。2017/3/31
下一篇UNIX編程基礎下:http://www.cnblogs.com/smartxuchao/p/6658060.html