系統調用與標準函數庫(上)

        所謂系統調用其實是操作系統提供給用戶程序的一組“特殊”函數接口,可以直接這麼去理解,操作系統是一個很大的“函數庫”,它給程序員提供了很多可以調用的函數。

       系統調用按照功能邏輯大致可分爲:進程控制、進程間通信、文件系統控制、系統控制、內存管理、網絡管理、socket控制、用戶管理。在Linux的不同版本中,提供了兩三百個系統調用,用戶程序可以通過這組接口獲得操作系統(內核)提供的服務。例如,用戶可以通過文件系統相關的系統調用,請求系統打開文件、關閉文件或讀寫文件。下圖是類UNIX系統的軟件層次圖:

                   

        應用程序可以通過系統調用接口陷入內核,內核再通過相應驅動程序去控制底層的硬件。當然應用程序進行系統調用有多種方式,如下圖所示:(1)應用程序直接調用系統調用,(2)通過shell命令,(3)通過標準庫函數,其實這些庫函數也都是系統調用的封裝出來的,比如fread()函數就是封裝系統調用read()而來的,當然並不是所有的系統調用都被封裝成了庫函數。

                                        


        1. 系統調用I/O函數

        系統調用中操作I/O的函數,都是針對文件描述符的,通過文件描述符可以直接對相應的文件進行操作,如:open、close、write 、read、ioctl。就像我C語言博文中關於文件操作那篇一樣,無非那些是標準庫下的函數,是對系統調用中操作I/O的函數封裝後的庫函數,原理都是一樣,C標準庫中有關文件的FILE結構體中包含了文件描述符和一些關於流緩衝區的信息。
        這裏簡單解釋下文件描述符的概念,文件描述符本質就是一個非負整數,是你在用open系統調用打開現存文件或新建文件時,系統(內核)返回給你的,它用來
指定已打開的文件

        #define STDIN_FILENO     0  //標準輸入的文件描述符

        #define STDOUT_FILENO 1 //標準輸出的文件描述符

        #define STDERR_FILENO 2 //標準錯誤的文件描述符
        上面這三個是特殊的文件描述符,在程序運行起來後是默認打開的。

        1.1 open函數:打開一個文件

        當文件存在時使用:int open(const char *pathname, int flags);
        當文件不存在時使用:int open(const char *pathname, int flags, mode_t mode);
        參數:pathname:文件的路徑及文件名。
                   flags:open函數的行爲標誌。
                   mode:文件權限(可讀、可寫、可執行)的設置。
        返回值:成功返回打開的文件描述符,失敗返回-1,可以利用perror去查看原因(下同)。

        1.2 close函數:關閉一個文件
        int close(int fd);
        參數:fd是調用open打開文件返回的文件描述符。
        返回值:成功返回0,失敗返回-1。

        1.3 read/write函數:把指定數目的數據讀到內存或寫到文件

        ssize_t read/write(int fd, const void *addr, size_t count);
        參數:fd:文件描述符。
        addr:內存首地址/數據首地址。
        count:寫入數據的字節個數。
        返回值:成功返回實際讀出/寫入數據的字節個數,失敗返回-1。

        1.4 remove函數:刪除文件
        int remove(const char *pathname); 
        參數:pathname :文件的路名+文件名。
        返回值:成功返回0,失敗返回-1。

        1.5 例系統調用實現cp命令

        #include <stdio.h>
        #include <stdlib.h>
        #include <malloc.h>
        #include <unistd.h>//write read
        #include <sys/types.h> //open
        #include <sys/stat.h>
        #include <fcntl.h>
        #define  BUF_SIZE 1024
        int main(int argc,char *argv[])
        {
                int fd_src,fd_dest;
                char buf[BUF_SIZE]="";
                int ret = 0;
                if(argc != 3)
                {
                        printf("miss parameters,please check your input!\n");
                        exit(-1);
                }
                else
                {
                        fd_src = open(argv[1],O_RDONLY);
                        fd_dest = open(argv[2],O_WRONLY|O_CREAT,0666);
                        if((fd_src == -1) || (fd_dest == -1))
                        {
                                perror("open file");
                                exit(-1);
                        }
                        //拷貝到目的文件
                        ret = read(fd_src,buf,BUF_SIZE);
                        while(ret > 0)
                        {
                                ret  = write(fd_dest,buf,ret);
                                if(ret == -1)
                               {
                                        perror("write file");
                                        exit(1);
                                }
                                ret = read(fd_src,buf,BUF_SIZE);
                        }
                        close(fd_src);
                        close(fd_dest);
                }
               return 0;
        }

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章