APUE學習筆記:第一章 UNUX基礎知識

1.2 UNIX體系結構linux

從嚴格意義上,可將操做系統定義爲一種軟件(內核),它控制計算機硬件資源,提供程序運行環境。內核的接口被稱爲系統調用。公用函數庫構建在系統調用接口之上,應用軟件便可使用公用函數庫,也可以使用系統調用。shell是一種特殊的應用程序,它爲運行其餘應用程序提供了一個接口shell

從廣義上,操做系統包括了內核和一些其餘軟件,這些軟件使得計算機可以發揮做用,並給予計算機以獨有的特性(軟件包括系統實用程序,應用軟件,shell以及公用函數庫等)編程

1.3  shellbash

shell是一個命令行解釋器,它讀取用戶輸入,而後執行命令。用戶一般用終端(交互式shell),有時則經過文件(shell script)向shell進行輸入編程語言

UNIX系統常見shell:函數

                        名稱                 路徑ui

        Boune shell:       /bin/shspa

        Bourne-again shell:  /bin/bash操作系統

        C shell:        /bin/csh.net

        Korn shell:      /bin/ksh

        TENEX C shell:    /bin/tcsh  

C shell其控制流相似於C語言,它支持Bourne shell沒有的某些特點功能,例如做業控制、歷史記憶機制以及命令行編輯等

Korn shell它與Bourne shell向上兼容,並具備使C shell普遍獲得應用的一些特點功能,包括做業控制以及命令行編輯

Bourne-again shell是GNUshell,全部linux都提供這種shell,它被設計成遵循POSIX的,同時也保留了與Bourne shell的兼容性。它支持C shell和Korn shell二者的特點功能

TENEX C shell 是C shell的增強版本。它從TENEX操做系統借鑑了不少特點,例如命令完備。TENEX C shell在C shell的基礎上增長了不少特徵,常被用來替換C shell

注:linux默認shell是Bourne-again shell.事實上,/bin/sh將連接到/bin/bash.FreeBSD 和Mac OS X的默認用戶shell是TENEX C shell,可是由於使用C shell編程語言極其困難,因此它們使用Bourne shell編寫用於管理方面的shell腳本

 

1.4文件和目錄

1.文件系統

UNIX文件系統是目錄和文件組成的一種層次結構,目錄的起點稱爲根(root),其名字是一個字符/。文件屬性是指文件類型(是普通文件仍是目錄)、文件大小、文件全部者、文件權限以及文件最後的修改時間等。

2.文件名

目錄中的各個名字稱爲文件名。不能出如今文件名中的字符只有斜線(/)和空操做符(null)兩個。

建立新目錄時會自動建立兩個文件名:.(當前目錄),..(父目錄)

3.路徑名

以斜線開頭的路徑名稱稱爲絕對路徑名,不然稱爲相對路徑名

實例:1-1 列出一個目錄中的全部文件

 1 #include"apue.h"
 2 #include<dirent.h>
 3 int main(int argc,char *argv[])    //argc表示參數個數;argv表示參數內容
 4 {
 5     DIR *dp;
 6     struct dirent *dirp;      
 7     if(argc!=2)
 8     err_quit("usage:ls directory_name");
 9     if((dp=opendir(argv[1]))==NULL)  //opendir函數返回指向DIR結構的指針
10     err_sys("can't open%s",argv[1]);
11     while((dirp=readdir(dp))!=NULL)  //readdir返回一個指向dirent結構的指針
12     printf("%s\n",dirp->d_name);
13     closedir(dp);
14    exit(0);
15 }

這段代碼相似於ls命令,不過這段代碼只打印一個目錄中各個文件的名字,不顯示其餘信息

編譯方法:$ cc xxx.c  編譯

              $ ./a.out  運行   

(可能不少初學者在編譯這段代碼時會出現找不到apue.h,這裏我發個配置apue.h頭文件的連接 http://www.linuxidc.com/Linux/2013-01/77686.htm)

 

1.5輸入與輸出

1.文件描述符

文件描述符一般是一個小的非負整數,內核用它標識一個特定進程訪問的文件。當內核打開一個已有文件或建立一個新文件時,它返回一個文件描述符。在讀寫文件時,就可使用它。

3.不用緩衝的I/O

函數open、read、write、lseek以及close提供了不用緩衝的I/O。這些函數都使用文件描述符

程序清單1_2 將標準輸入複製到標準輸出

 1 #include"apue.h"
 2 #define BUFFSIZE 4096
 3 int main(void)
 4 {
 5     int n;
 6     char buf[BUFFSIZE];
 7     while((n=read(STDIN_FILENO,buf,BUFFSIZE))>0)
 8         if(write(STDOUT_FILENO,buf,n)!=n)
 9             err_sys("write error");
10         if(n<0)
11         err_sys("read error");
12     exit(0);
13 }


4.標準I/O

標準I/O函數提供一種對不用緩衝I/O函數的帶緩衝的接口。使用標準I/O函數能夠無需擔憂如何選取最佳的緩衝區大小,例如1_2中BUFFSIZE常量的大小。使用標準I/O函數的另外一個優勢是簡化了對輸入行的處理。例如,fgets函數讀一完整的行,而read函數讀指定字節數。(printf函數即是標準I/O函數)

實例:1_3 用標準I/O將標準輸入複製到標準輸出

 1 #include"apue.h"
 2 int main()
 3 {
 4     int c;
 5     while((c=getc(stdin))!=EOF)
 6         if(putc(c,stdout)==EOF)
 7         err_sys("output error");
 8     if(ferror(stdin))
 9     err_sys("input error");
10     exit(0);
11 }

附:無緩衝I/O操做和標準I/O操做的區別 http://blog.csdn.net/cowbane/article/details/6630298

 

1.6程序和進程

1.程序是存放在磁盤上,處於某個目錄中的一個可執行文件。使用6個exec函數中的一個由內核將程序讀入存儲器,並使其執行

2.進程和進程ID

程序的執行實例被稱爲進程。UNIX系統確保每一個進程都有一個唯一的數字標識符,稱爲進程ID,進程ID老是一非負整數

實例:1_4 打印進程ID

1 #include"apue.h"
2 int main()
3 {
4     printf("hello world from process ID %d\n",getpid());
5     exit(0);
6 }

此程序運行時,它調用函數getpid獲得其進程ID

3.進程控制

有三個用於進程控制的主要函數:fork,exec和waitpid

實例: 1_5 從標準輸入讀命令並執行(類shell程序)

 1 #include"apue.h"
 2 #include<sys/wait.h>
 3 4 
 5 int main(void)
 6 {
 7     char buf[MAXLINE];
 8     pid_t pid;    
 9     int status;

13     printf("%% ");
14     while(fgets(buf,MAXLINE,stdin)!=NULL){
15     if(buf[strlen(buf)-1]=='\n')
16     buf[strlen(buf)-1]=0;             //用null替換換行符
17     if((pid=fork())<0){            //fork向父進程返回新子進程的進程ID(非負),對子進程則返回0;因此說它被調用一次,返回兩次
18     err_sys("fork error");
19     }
20     else if(pid==0){          
21     execlp(buf,buf,(char *)0);    //execlp執行從標準輸入讀入的命令。fork和跟隨其後的exec二者的組合是某些操做系統所稱的產生(spawn)一個新進程
22     err_ret("couldn't execute:%s",buf);
23     exit(127);
24     }
25     if((pid=waitpid(pid,&status,0))<0)    //waitpid函數返回子進程的終止狀態
26     err_sys("waitpid error");
27     printf("%% ");
28     }
29     exit(0);
30 }

該程序的主要限制是不能向所執行的命令傳遞參數,例如不能指定要列表的目錄名,只能對工做目錄執行ls命令

4.線程和線程ID

在一個進程內的全部線程共享同一地址空間、文件描述符、棧以及進程相關的屬性。線程ID只在它所屬進程內起做用。一個進程中的線程ID在另外一個進程中並沒有意義。

1.7出錯處理

當unix函數出錯時,經常返回一個負值,並且整型變量errno一般被設置爲含有附加信息的一個值。例如,open函數如成功執行則返回一個非負文件描述符,如出錯則返回-1。

實例:1_6 示例strerror和perror兩個出錯函數的使用方法

1 #include"apue.h"
2 #include<errno.h>
3 int main(int argc,char *argv[])
4 {
5     fprintf(stderr,"EACCES: %s\n",strerror(EACCES));
6     errno=ENOENT;
7     perror(argv[0]);
8     exit(0);
9 }

 

1.8用戶標識

用戶ID 和組ID

示例:1_7 打印用戶ID和組ID

1 #include"apue.h"
2 int main()
3 {
4     printf("uid=%d,gid= %d,\n",getuid(),getgid());
5     exit(0);
6 }

1.9信號

信號是通知進程已發生某種狀況的一種技術。

進程處理信號有三種選擇:a.忽略該信號

            b.按系統默認方式處理。對於除以0的狀況,系統默認是終止該進程

            c.提供一個函數,信號發生時則調用該函數,這被稱爲捕捉該信號。使用這種方式,咱們只要提供自編的函數就將能知道何時產生了信號,並按所但願             的方式處理它

實例:1_8 從標準輸入讀命令並執行(比1_5多了信號處理)

 1 #include"apue.h"
 2 #include<sys/wait.h>
 3 static void sig_int(int);
 4 
 5 int main(void)
 6 {
 7     char buf[MAXLINE];
 8     pid_t pid;    
 9     int status;
10     if(signal(SIGINT,sig_int)==SIG_ERR)
11     err_sys("signal error");
12 
13     printf("%% ");
14     while(fgets(buf,MAXLINE,stdin)!=NULL){
15     if(buf[strlen(buf)-1]=='\n')
16     buf[strlen(buf)-1]=0;
17     if((pid=fork())<0){
18     err_sys("fork error");
19     }
20     else if(pid==0){
21     execlp(buf,buf,(char *)0);
22     err_ret("couldn't execute:%s",buf);
23     exit(127);
24     }
25     if((pid=waitpid(pid,&status,0))<0)
26     err_sys("waitpid error");
27     printf("%% ");
28     }
29     exit(0);
30 }
31     void sig_int(int signo)
32     {
33         printf("interrupt\n%%");
34     }

1.10時間值

UNIX系統使用三個進程時間值:時鐘時間,用戶cpu時間,系統cpu時間

時鐘時間又稱爲牆上時鐘時間(wall clock time)。它是進程運行的時間總量,其值與系統中跟同時運行的進程數有關。

用戶CPU時間是執行用戶指令所用的時間。

系統cpu時間是爲該進程執行內核程序所經歷的時間

例如:每當一個進程執行一個系統服務時,如read或write,則在內核內執行該服務所花費的時間就計入該進程的系統cpu時間。用戶cpu時間和系統cpu時間之和常被稱爲cpu時間

 

 

取得任意進程的時鐘時間,用戶時間,和系統時間:$cd /usr/include;time -p grep _POSIX_SOURCE */*.h > /dev/null

相關文章
相關標籤/搜索