Linux高級環(huán)境編程

1. 編譯的四個步驟:

  • 預(yù)處理
    gcc -E test.c -o test.i
  • 編譯:將高級語言編譯成匯編語言
    gcc -S test.c -o test.s
  • 匯編:將匯編語言編譯成二進制的目標代碼
    gcc -c test.c -o test.o
  • 鏈接:包含各函數(shù)的入口严拒,得到可執(zhí)行代碼
    gcc -o test test.c

2. gdb調(diào)試

(1) 在編譯時,需要加上調(diào)試信息-g參數(shù)邓厕;
l:list列出各行編號草讶;
n:next下一行執(zhí)行洽糟;
c:continue下一個斷點;
b 行號:在相應(yīng)的行號設(shè)置斷點堕战;
p 變量名:打印這個變量的值坤溃。

3. 系統(tǒng)限制

  • 本身平臺的限制:32位平臺or64位平臺
  • 數(shù)據(jù)類型的限制:/usr/include/limits.h
  • 系統(tǒng)本身的限制:系統(tǒng)的資源是有限的,不可能無限制的申請資源
    命令行:ulimit來修改和獲取
    編程時:getrlimit函數(shù)獲取践啄,setrlimit來設(shè)置系統(tǒng)的限制浇雹,可用man getrlimit查看

4. 命令行參數(shù)

getopt:獲取短選項
getlongopt:獲取長選項
以下全局變量要配合getopt函數(shù):

extern char* optarg;
extern int optind;
extern int optopt;
extern int opterr;

5. 程序結(jié)構(gòu)與進程的結(jié)構(gòu)

一個可執(zhí)行程序包含三個部分:
  • 代碼段(text):主要存放指令,操作以及只讀的(常量)數(shù)據(jù)
  • 數(shù)據(jù)段(data):全局或者靜態(tài)的已經(jīng)初始化的變量
  • BBS段(bbs):全局或者靜態(tài)的未初始化的變量
執(zhí)行一個程序(存放在外存中)屿讽,系統(tǒng)如何為其中申請的內(nèi)存空間昭灵?

進程:Linux操縱系統(tǒng)最小資源管理單元,一個程序運行伐谈,必然首先為其創(chuàng)建一個(或多個)進程烂完,進程是有生命周期的,一個進程是執(zhí)行的程序段诵棵,資源有哪些抠蚣?
因為在程序的執(zhí)行時,會動態(tài)的申請空間履澳,執(zhí)行子函數(shù)嘶窄,因此Linux對一個進程的管理采用以下方式:
在執(zhí)行程序時怀跛,系統(tǒng)首先在內(nèi)核空間中創(chuàng)建一個進程,為這個進程申請一個PCB(進程控制塊tast_struct)柄冲,用于管理整個進程的所有資源吻谋。其中mm_struct成員用來管理與當(dāng)前進程相關(guān)的所有內(nèi)存資源。(內(nèi)存資源包含(1)代碼段现横,數(shù)據(jù)段漓拾,BBS段。這三個段直接從磁盤拷貝到當(dāng)前內(nèi)存空間戒祠,大小相等骇两。(2)動態(tài)空間:堆,椊空間低千,mmap段[映射其他的庫相關(guān)的信息])

在Linux系統(tǒng)中查看進程信息:

搜索指定進程的相關(guān)信息

有關(guān)ps aux|grep a.out詳細信息移步鏈接,其中第二列的數(shù)字表示進程的pid馏颂。
查看進程映射文件maps信息

起始地址和終止地址并不是真正的物理地址栋操,而是虛擬地址空間,為什么需要虛擬地址饱亮?是出于堆資源的保護矾芙,對系統(tǒng)來說,內(nèi)存資源是寶貴的近上,而一個程序執(zhí)行并不需要立即將所有的資源全部加載到內(nèi)存中剔宪,而實際上棵采用寫時申請的方式
好處:(1)保護系統(tǒng):用戶程序非法訪問造成內(nèi)核的崩潰壹无,因此發(fā)生段錯誤葱绒,使執(zhí)行這個非法訪問的進程自動退出。(2)節(jié)約資源:采用內(nèi)存映射的方法斗锭,一個程序執(zhí)行時并不是立即將所有的代碼和空間映射到內(nèi)存空間地淀,而是使用時用缺頁的方法真正申請內(nèi)存空間,一是提高效率岖是,二是節(jié)約內(nèi)存空間帮毁。
在32為平臺中,一個進程擁有自己的4G的虛擬空間豺撑,與其他進程無關(guān)烈疚,因此進程與進程之間是獨立的

6. 進程空間的地址申請

(1) 代碼段聪轿,數(shù)據(jù)段爷肝,BSS段,這三個部分直接從磁盤拷貝到內(nèi)存。起始地址在當(dāng)前的32位平臺linux下為0x0804a000地址灯抛。
(2) 堆金赦。動態(tài)變化。malloc系列申請对嚼。
(3) mmap映射文件(普通文件素邪,也可以是其他類型的文件)
(4) 棧段。
(5)高地址1G空間共內(nèi)核映射處理的猪半。用戶不能直接處理。

堆和棧的起始地址默認是隨機參數(shù)的偷线,其目的是避免安全漏洞

堆:可以在堆中申請空間的起始地址(通過brksbrk來改變)
int brk(void *addr);:指定下次申請堆空間的起始地址為addr
void *sbrk(intptr_t increment);:為當(dāng)前的地址位置后移increment字節(jié)磨确,如果為0,返回當(dāng)前值

系統(tǒng)執(zhí)行一個進程声邦,到底怎么加載這些空間乏奥?——使用strace工具查看

堆空間的起始地址是隨機的,可以設(shè)置不隨機亥曹,大小也可以設(shè)置固定大小
(1)代碼段邓了、數(shù)據(jù)段、BSS段的地址已經(jīng)在編譯鏈接時固定
(2)在BSS段結(jié)束與堆起始地址有間隙媳瞪,這個大小時隨機值**
(3) brk函數(shù)僅僅是調(diào)整在堆中申請空間的起始值
(4)系統(tǒng)默認為每個進程分配的堆空間的大小是固定的骗炉。使用sbrk(0)得到的是我們堆空間的結(jié)束值。第一次是使用malloc申請資源返回的地址接近堆空間的起始值蛇受。使用brk(addr)改變的是新申請數(shù)據(jù)的堆空間起始值
(5)在真正編程時句葵,很少用brk/sbrk,使用malloc函數(shù)來新申請堆空間兢仰,效率更高乍丈。部分時間使用mmap來映射mmap區(qū)。

棧:棧從高地址向低地址增長把将,棧的起始地址也是隨機的轻专。棧中主要存放的是局部變量,新調(diào)用的子函數(shù)時函數(shù)的參數(shù)及返回值察蹲,由OS自動管理请垛。

7. 編程中內(nèi)存的申請與釋放

  • 代碼段:由只讀數(shù)據(jù)(const字符串常量)和代碼組成。這些內(nèi)容的空間在編譯鏈接時申請且指定存儲地址洽议。
  • 數(shù)據(jù)段和BSS段:定義的全局的或者靜態(tài)的變量叼屠。已經(jīng)初始化的在數(shù)據(jù)段,未初始化的在BSS段中绞铃。這些內(nèi)容的空間在編譯鏈接時申請且指定存儲地址镜雨。
    以上空間的申請在運行之時就加載到內(nèi)存中,直到程序的結(jié)束,都不在發(fā)生變化(除exceX函數(shù)替換外)荚坞。因此這些變量申請的空間生存周期就是整個程序挑宠,如果在相應(yīng)的作用域中,可一直訪問颓影,也可以根據(jù)這個變量的地址訪問各淀。

通過符號訪問一個變量,要在他的作用域中诡挂,但是碎浇,對于以上三個段中的數(shù)據(jù),只要知道地址璃俗,其實可以通過地址間接訪問這個空間奴璃,且在整個程序執(zhí)行期間都可以訪問。在編程中城豁,以上空間的申請就是定義相應(yīng)的變量或者常量苟穆。

  • 堆。動態(tài)申請唱星,在C中用malloc/delete等雳旅,C++中用malloc/delete
    堆的起始位置由brk函數(shù)來指定间聊。但具體編程中攒盈,一般不會自己使用brk函數(shù),而是使用malloc庫函數(shù)哎榴。內(nèi)核對內(nèi)存的管理是頁式管理沦童,因此在malloc申請空間時,使用鏈式結(jié)構(gòu)來管理已經(jīng)申請的堆空間叹话。
    void *calloc(size_t nmemb, size_t size);
    void *malloc(size_t size);:申請指定大小的內(nèi)存空間偷遗,虛擬地址空間
    void free(void *ptr);:釋放內(nèi)存空間
    void *realloc(void *ptr, size_t size); :調(diào)整已經(jīng)申請的堆中的數(shù)據(jù)空間
    注意事項:
    (1) ptr_new = realloc(ptr, 200)在真正實現(xiàn)上,如果ptr后有足夠的空間驼壶,則直接擴展氏豌;如沒有足夠的空間,會重新查找一個(>=200)大小空間热凹,將原來的數(shù)據(jù)復(fù)制到新的空間中泵喘,然后釋放原來的空間。如果查找不到足夠的空間般妙,則返回null纪铺。因此不能直接寫ptr= realloc(ptr, 200),這樣如果申請失敗碟渺,會丟失原來的ptr
    (2)free(ptr)時鲜锚,需要加一句ptr = NULL,來避免后面的雙重釋放。
    (3)申請和釋放一定需要匹配芜繁,避免不必要的內(nèi)存泄露

  • 棧旺隙。動態(tài)申請。椏チ睿空間在加載程序蔬捷,創(chuàng)建進程時就申請了一個范圍,棧是由OS來主要管理榔袋。
    需要考慮兩個問題:為什么不能返回局部變量的地址周拐?局部變量的生命周期是怎樣的?
    對于未申請的堆空間地址訪問凰兑,一般會出現(xiàn)段錯誤妥粟;
    對于已經(jīng)釋放的函數(shù)棧空間的訪問聪黎,一般不會出現(xiàn)段錯誤,但是是非法訪問备恤,是不允許的稿饰;
    在編程中,對任何空間的訪問一定要保證這個空間已經(jīng)申請且在控制范圍內(nèi)露泊。
    對任何空間地址值的操作僅僅是數(shù)據(jù)的操作喉镰,沒有任何的問題。

  • mmap的庫以及相關(guān)文件惭笑。將一個文件內(nèi)容的全部或部分映射到虛擬地址空間中侣姆,操作這段內(nèi)存空間會同步到磁盤文件的操作,效率比較高沉噩。

       #include <sys/mman.h>

       void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
       int munmap(void *addr, size_t length);

// 參數(shù)意義:
void *mmap(
        void *addr,     // 映射到哪個虛擬地址捺宗,一般為NULL生闲,讓系統(tǒng)選擇厕氨;如果自己設(shè)置蔓挖,最好是頁的整數(shù)倍讶踪,getpagesize
        size_t length,   // 大小
        int prot,       
        int flags, 
        int fd,       // 加載的文件對應(yīng)打開的文件描述符
        off_t offset  // 偏移量禾乘,從文件哪個位置開始
);

prot:
       PROT_EXEC  Pages may be executed.
       PROT_READ  Pages may be read.
       PROT_WRITE Pages may be written.
       PROT_NONE  Pages may not be accessed.
flags:
       MAP_SHARED Share this mapping.  Updates to the mapping are visible to other processes that map this file,
                  and  are  carried  through to the underlying file.  The file may not actually be updated until
                  msync(2) or munmap() is called.

       MAP_PRIVATE
                  Create a private copy-on-write mapping.  Updates to the mapping are not visible to other  pro‐
                  cesses  mapping  the  same  file,  and  are not carried through to the underlying file.  It is
                  unspecified whether changes made to the file after the mmap() call are visible in  the  mapped
                  region.

8. 常見的內(nèi)存錯誤以及valgrind使用

  • 代碼段:這部分為只讀數(shù)據(jù)秉继。因此對這個一部分的數(shù)據(jù)统台,試圖寫只讀數(shù)據(jù)蝠咆,編譯的時候會報waring康聂。
  • 數(shù)據(jù)段/BSS段:未初始化直接訪問贰健,即使沒有顯示初始化,仍然會初始化為0恬汁。
  • 棧數(shù)據(jù)空間:為局部變量伶椿,未初始化會給隨機值;棧溢出,在棧中申請過大的局部變量悬垃。
  • 堆空間:內(nèi)存泄漏游昼,申請未釋放;申請后尝蠕,雙重釋放
  • 對于所有的地址空間:
    (1)野指針問題烘豌,訪問未初始化指針,
    (2)越界訪問
    (3)非法的越界文芳
    (4)空間不再控制范圍仍然去訪問空間

使用工具:來檢測常見的內(nèi)存錯誤看彼,valgrind工具廊佩。
gcc -o valgrind_example01 valgrind_example01.c -g

valgrind --tool=memcheck --show-reachable=yes --read-var-info=yes --verbose --time-stamp=yes --leak-check=full--log-file=mycode.log ./valgrind_example01

less mycode.log
如果要使用圖形化的工具,要安裝QT靖榕,這個工具名字叫valkyrie

9.Posix磁盤文件內(nèi)容管理—文件描述符

  • Linux操作系統(tǒng)內(nèi)核態(tài)與用戶態(tài):

    用戶態(tài)與內(nèi)核態(tài)
    應(yīng)用空間提出申請标锄,OS會在資源可用的情況下返回一個ID。用戶空間會通過這個ID來訪問對應(yīng)的資源茁计。
    磁盤文件也是由OS來管理料皇,因此,要訪問磁盤文件需要系統(tǒng)調(diào)用

  • 怎么讓一個程序(進程)與要操作的文件建立聯(lián)系星压?


    要去訪問磁盤的文件践剂,必須通過系統(tǒng)調(diào)用來返回一個與該文件相關(guān)的ID,這個ID就是文件描述符(file descriptor)

具體過程:
Linux操作系統(tǒng)提供了open系統(tǒng)調(diào)用娜膘,任何的進程要去訪問一個文件逊脯,首先使用open打開這個文件,系統(tǒng)將返回一個編號竣贪,即與這個文件相關(guān)聯(lián)的文件描述符军洼。
(1)用戶程序從用戶空間向內(nèi)核提交了打開申請;
(2)操作系統(tǒng)會在內(nèi)核中去檢查請求是否合法演怎,如果合法匕争,在內(nèi)核中申請這個打開文件相關(guān)的信息(讀寫位置,在磁盤中的位置......全用struct files來存儲)爷耀。并添加到當(dāng)前的PCB塊中的打開文件列表數(shù)組中汗捡。對應(yīng)的這個數(shù)組下標即為文件描述符值
(3)將這個文件描述符返回給用戶空間畏纲,用戶空間接下來對這個文件進行讀寫就通過這個編號值扇住。

進程對磁盤的訪問

系統(tǒng)默認為每個進程打開三個文件:
文件描述符0(標準輸入,鍵盤STDIN_FILENO)盗胀, 1(標準輸出艘蹋,顯示器STDOUT_FILENO), 2(標準錯誤輸出票灰,顯示器STDERR_FILENO)

10.Posix磁盤文件內(nèi)容管理—系統(tǒng)調(diào)用函數(shù)

  • 建立與斷開聯(lián)系open/close:即進程與磁盤建立/斷開聯(lián)系
       #include <sys/types.h>
       #include <sys/stat.h>
       #include <fcntl.h>

       int open(const char *pathname, int flags);
       int open(const char *pathname, int flags, mode_t mode);

       int creat(const char *pathname, mode_t mode);

參數(shù)說明:
pathname:打開文件路徑
flags:打開方式標志
   O_RDONLY :只讀
   O_WRONLY:只寫
   O_RDWR:讀寫
   O_APPEND:追加
mode:文件權(quán)限
  新創(chuàng)建一個文件的真正權(quán)限是mode & ~umask女阀,

這個文件打開成功宅荤,將返回一個新的文件描述符值,
后面針對這個文件的操作就是用這個文件描述符浸策。

// 示例代碼
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char* argv[])
{
    int fd;

    fd = open(argv[1], O_RDONLY|O_CREAT, 0644);

    if( -1 == fd )
    {
        perror("open");
        exit(EXIT_FAILURE);
    }

    printf("fd: %d\n", fd);

    close(fd);

    return 0;
}

  • 讀寫文件內(nèi)容read/write冯键,即將磁盤中的內(nèi)容讀到內(nèi)存/將內(nèi)存中的內(nèi)容寫入磁盤
       #include <unistd.h>

       ssize_t read(int fd, void *buf, size_t count);
// 從fd所指向的文件中讀取count字節(jié)到buf為首地址的內(nèi)存空間中
       ssize_t write(int fd, const void *buf, size_t count);
// 往fd所指向的文件中寫入count字節(jié),這個內(nèi)容存放在buf為首地址的內(nèi)存空間中
  • 文件位置的修改lseek:對當(dāng)前文件的讀寫位置進行定位庸汗,可以在文件中添加空洞惫确。
       #include <sys/types.h>
       #include <unistd.h>

       off_t lseek(int fd, off_t offset, int whence);
DESCRIPTION
       The  lseek()  function  repositions the offset of the open file associated with the file descriptor fd to
       the argument offset according to the directive whence as follows:

       SEEK_SET   // 文件開頭
              The offset is set to offset bytes.
       SEEK_CUR  // 文件當(dāng)前位置
              The offset is set to its current location plus offset bytes.
       SEEK_END  // 文件結(jié)尾
              The offset is set to the size of the file plus offset bytes.

       The lseek() function allows the file offset to be set beyond the end of  the  file  (but  this  does  not
       change  the  size  of the file).  If data is later written at this point, subsequent reads of the data in
       the gap (a "hole") return null bytes ('\0') until data is actually written into the gap.

也可以用這個函數(shù)來實現(xiàn)文件大小的獲取。把文件的讀寫位置設(shè)置為文件結(jié)束蚯舱,因為這個函數(shù)返回當(dāng)前讀寫位置距離文件頭的偏移字節(jié)數(shù)改化。

11.Posix磁盤文件內(nèi)容管理—文件描述符復(fù)制與鎖定

  • 復(fù)制功能,用處:在重定向應(yīng)用中cat test>test.txt
    dup/dup2/fcntl
    復(fù)制后枉昏,兩個文件描述符都指向同一個文件表項陈肛,即使用這兩個文件描述符中的一個就會影響讀寫相關(guān)的信息
       #include <unistd.h>

       int dup(int oldfd);  //復(fù)制oldfd這個文件描述符兄裂,返回在調(diào)用此函數(shù)前最小未使用的文件描述符值句旱。
       close(0);
       dup(3);
       這個代碼可以實現(xiàn)輸入的重定向。
       默認從0讀數(shù)據(jù)晰奖,現(xiàn)在0指向的表項被復(fù)制為3谈撒,
       這樣從0讀實際上就是從3指向的文件讀,
       也就實現(xiàn)的輸入的重定向畅涂。
       int dup2(int oldfd, int newfd);  // 把oldfd復(fù)制為newfd港华,如果newfd已經(jīng)對應(yīng)一個打開的文件道川,則先關(guān)閉它午衰。
       dup2(3,0);

       #include <unistd.h>
       #include <fcntl.h>

       int fcntl(int fd, int cmd, ... /* arg */ );
       cmd為:F_DUPFD時為復(fù)制文件描述符
  • 鎖定功能:并發(fā)的環(huán)境下,除了使用并發(fā)的工具來保護共享文件外冒萄,也可以使用文件鎖臊岸。flock/fcntl
       #include <sys/file.h>

       int flock(int fd, int operation);
參數(shù): operation
           LOCK_SH  Place a shared lock.  More than one process may hold a shared lock for a  given  file  at  a given time.
           LOCK_EX  Place  an exclusive lock.  Only one process may hold an exclusive lock for a given file at a given time.
           LOCK_UN  Remove an existing lock held by this process.

強調(diào)一下:這里指的是鎖定文件描述符,鎖定的是整個文件表項尊流,防止被其他的進程訪問帅戒,鎖整個文件。
如果要鎖定某一部分崖技,可以用fcntl

       #include <unistd.h>
       #include <fcntl.h>

       int fcntl(int fd, int cmd, ... /* arg */ );
cmd:
       F_GETLK, F_SETLK and F_SETLKW are used to acquire, release, and test for the existence  of  record  locks
       (also known as file-segment or file-region locks).  The third argument, lock, is a pointer to a structure
       that has at least the following fields (in unspecified order).

           struct flock {
               ...
               short l_type;    /* Type of lock: F_RDLCK,
                                   F_WRLCK, F_UNLCK */
               short l_whence;  /* How to interpret l_start:
                                   SEEK_SET, SEEK_CUR, SEEK_END */
               off_t l_start;   /* Starting offset for lock */
               off_t l_len;     /* Number of bytes to lock */
               pid_t l_pid;     /* PID of process blocking our lock
                                   (F_GETLK only) */
               ...
           };
  • 屬性控制逻住、權(quán)限狀態(tài)、擁有者等
    使用fcntl

  • 提高效率迎献, 同步磁盤
    可以使用mmap函數(shù)來某個打開的文件映射到虛擬地址空間瞎访,以后操作這個虛擬地址空間就類似于操作這個文件。

實現(xiàn)大于2G的文件的拷貝操作吁恍。如果文件大于2G扒秸,偏移超過int_32類型的限制播演,為了實現(xiàn)大文件的拷貝,必須使用宏伴奥。方法如下
(1)在所有的頭文件包含前加上
#define _LARGEFILE_SOURCE
#define _FILE_OFFSET_BITS 64
(2)在編譯時写烤,加上宏
gcc -D _LARGEFILE_SOURCE -D _FILE_OFFSET_BITS =64

12文件流與目錄流管理—ANSI文件流,文件描述符與緩沖區(qū)類型

問題一:每執(zhí)行一次讀寫拾徙,都要執(zhí)行系統(tǒng)調(diào)用洲炊,系統(tǒng)調(diào)用會導(dǎo)致CPU的切換,比較耗時锣吼,頻繁的讀寫會導(dǎo)致耗時較多选浑。
問題二:使用系統(tǒng)調(diào)用時,可移植性問題玄叠。

  • 為了提高效率古徒,ANSI C提出了文件流的概念,即在用戶空間的文件描述符的基礎(chǔ)上進行封裝读恃,添加緩沖區(qū)和讀寫位置信息隧膘,使功能更強。

  • 流的一個重要提高效率的辦法是使用緩沖區(qū)寺惫,將多次的系統(tǒng)調(diào)用合并成一次系統(tǒng)調(diào)用疹吃,節(jié)約執(zhí)行的時間。

  • 流和緩沖區(qū):
    全緩沖:只有當(dāng)數(shù)據(jù)量達到某個限制后(不同的平臺有差異西雀,通常為4096)萨驶,或者主動的要求刷新緩沖區(qū)(如close()/fflush),才真正執(zhí)行一定的系統(tǒng)調(diào)用操作艇肴。常見的哪些流是全緩沖:文件流腔呜,即以fopen打開的文件。
    行緩沖:只有當(dāng)數(shù)據(jù)量達到某個限制后(不同的平臺有差異再悼,通常為128或1024)核畴,或者遇到換行,或者主動的要求刷新緩沖區(qū)冲九,才真正執(zhí)行一定的系統(tǒng)調(diào)用操作谤草。常見的哪些流是行緩沖:終端命令行。
    無緩沖:需要實時顯示信息的莺奸,例如標準的錯誤輸出丑孩,如fprintf(stderr)

  • 默認的三個打開的文件對應(yīng)的流:

/* Standard streams.  */
extern struct _IO_FILE *stdin;            /* Standard input stream.  */
extern struct _IO_FILE *stdout;           /* Standard output stream.  */
extern struct _IO_FILE *stderr;           /* Standard error output stream.  */
  • 如果要修改緩沖的類型或者自己指定對應(yīng)緩沖區(qū)的位置,可以使用setbuf/setvbuf
       #include <stdio.h>

       void setbuf(FILE *stream, char *buf);
       void setbuffer(FILE *stream, char *buf, size_t size);
       void setlinebuf(FILE *stream);
       int setvbuf(FILE *stream, char *buf, int mode, size_t size);

參數(shù)mode:
     _IONBF unbuffered
     _IOLBF line buffered
     _IOFBF fully buffered

13文件流與目錄流管理—ANSI文件流操作函數(shù)詳解

  • 文件流的操作:編程中用到的函數(shù)是ANSI庫函數(shù)灭贷,之前用到的open/read/write/close為系統(tǒng)調(diào)用函數(shù)
  • 打開/關(guān)閉open/close
       #include <stdio.h>

       FILE *fopen(const char *path, const char *mode);
       參數(shù)說明:
       path:打開文件路徑
       mode:打開方式
         r:只讀温学,對應(yīng)系統(tǒng)文件中的open->O_RDONLY
         w:只寫,open->O_WRONLY|O_CREAT|O_TRUNC
         a:追加氧腰,open->O_APPEND|O_CREAT|O_WRONLY
         X+:可讀可寫枫浙,open->RDWR

       FILE *fdopen(int fd, const char *mode);
       將一個文件描述符封裝成一個流
       FILE *freopen(const char *path, const char *mode, FILE *stream);
       將原來的stream重新封裝成另外mode的流

使用完成后close這個流對象刨肃,期間會刷新流的緩沖區(qū)
  • 讀/寫
       int fgetc(FILE *stream);

       char *fgets(char *s, int size, FILE *stream);

       int getc(FILE *stream);

       int getchar(void);

       char *gets(char *s);

       int ungetc(int c, FILE *stream);


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市箩帚,隨后出現(xiàn)的幾起案子真友,更是在濱河造成了極大的恐慌,老刑警劉巖紧帕,帶你破解...
    沈念sama閱讀 222,865評論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件盔然,死亡現(xiàn)場離奇詭異,居然都是意外死亡是嗜,警方通過查閱死者的電腦和手機愈案,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,296評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來鹅搪,“玉大人站绪,你說我怎么就攤上這事±鍪粒” “怎么了恢准?”我有些...
    開封第一講書人閱讀 169,631評論 0 364
  • 文/不壞的土叔 我叫張陵,是天一觀的道長甫题。 經(jīng)常有香客問我馁筐,道長,這世上最難降的妖魔是什么坠非? 我笑而不...
    開封第一講書人閱讀 60,199評論 1 300
  • 正文 為了忘掉前任敏沉,我火速辦了婚禮,結(jié)果婚禮上炎码,老公的妹妹穿的比我還像新娘盟迟。我一直安慰自己,他們只是感情好辅肾,可當(dāng)我...
    茶點故事閱讀 69,196評論 6 398
  • 文/花漫 我一把揭開白布队萤。 她就那樣靜靜地躺著轮锥,像睡著了一般矫钓。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上舍杜,一...
    開封第一講書人閱讀 52,793評論 1 314
  • 那天新娜,我揣著相機與錄音,去河邊找鬼既绩。 笑死概龄,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的饲握。 我是一名探鬼主播私杜,決...
    沈念sama閱讀 41,221評論 3 423
  • 文/蒼蘭香墨 我猛地睜開眼蚕键,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了衰粹?” 一聲冷哼從身側(cè)響起锣光,我...
    開封第一講書人閱讀 40,174評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎铝耻,沒想到半個月后誊爹,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,699評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡瓢捉,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,770評論 3 343
  • 正文 我和宋清朗相戀三年频丘,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片泡态。...
    茶點故事閱讀 40,918評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡搂漠,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出某弦,到底是詐尸還是另有隱情状答,我是刑警寧澤,帶...
    沈念sama閱讀 36,573評論 5 351
  • 正文 年R本政府宣布刀崖,位于F島的核電站惊科,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏亮钦。R本人自食惡果不足惜馆截,卻給世界環(huán)境...
    茶點故事閱讀 42,255評論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蜂莉。 院中可真熱鬧蜡娶,春花似錦、人聲如沸映穗。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,749評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蚁滋。三九已至宿接,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間辕录,已是汗流浹背睦霎。 一陣腳步聲響...
    開封第一講書人閱讀 33,862評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留走诞,地道東北人副女。 一個月前我還...
    沈念sama閱讀 49,364評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像蚣旱,于是被迫代替她去往敵國和親碑幅。 傳聞我的和親對象是個殘疾皇子戴陡,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,926評論 2 361

推薦閱讀更多精彩內(nèi)容