時光飛逝,轉眼已經畢業快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
