unix 環境高級編程(1)

既然已經做出決定,就要努力走下去。
文件和目錄
unix 文件系統是目錄和文件的一種層次, 所有東西的起點是成爲根的目錄,名稱“/”
創建新目錄時系統會自動創建兩個文件名:. 和.. , . 表示當前目錄, ..表示父親目錄
標準輸入文件描述符 0 標準輸出文件描述符 1 重定向 ./a.out > data a.out的輸出重定向至文件data ./a.out outfile 將 infiel 複製到 outfile
程序 進程
程序時一個存儲在磁盤上某個目錄中的可執行文件。內核使用exec函數將程序讀入內存,
進程:程序執行的實例,進程控制的主要函數 frok exec waitpid
文件描述符: 對內核而言,所有打開的文件都會通過文件描述符引用,是非負數, 當讀寫時通過 open或者creat 返回的文件描述符表示該文件,將其作爲參數送給read或者write, 系統shell把文件描輸入0 與進程的標準輸入關聯,文件描述符1與標準輸出關聯,文件描輸入2 與 標準錯誤關聯,
open openat 函數返回的描述符一定時最小的未使用描述符的數值
open(path , flag, …)
openat(fd, path, flag..)
fd 把 open 和 spenat 區分開來:
如果path是絕對路徑, 二者沒區別
如果path是相對路徑, fd參數之處了相對路徑在文件系統中的開售位置,fd參數是通過打開相對路徑所在的目錄來獲取
path是相對路徑, fd 參數爲 AT_FDCWD 在這種情況下,路徑名在當前工作目錄中獲取
create(path, mode) close(fd)
lseek 設置文件偏移量,


#include <fcntl.h>

int main(){
   int fd;
   char buf[] = "abcdefghij";
   if((fd = open("test.txt", O_RDWR|O_APPEND)) == -1){
       err_sys("open error!");
   }
   if(lseek(fd, 0, SEEK_SET) == -1)
     err_sys("lseek error");
   if(write(fd, buf, 10) != 10)
     err_sys("write error");
   close(fd);



   char buf1[] = "abcdefghij";
   if((fd = open("test.txt", O_RDWR|O_APPEND)) == -1){
       err_sys("open error!");
   }
   if(lseek(fd, 0, SEEK_SET) == -1)
     err_sys("lseek error");
   if(read(fd, buf1, 10) != 10)
     err_sys("read error");
    printf("%s",buf1);
   close(fd);

可以通過 od 來觀察文件的實際內容
注意: 當 文件打開mode 設置爲 O_APPEND時,無論怎樣設置偏移量文件的寫操作總是進行在文件的末尾,讀操作則可以從偏移量開始。
文件的偏移量可以爲負值,所以在監測時,應監測他是不是等於-1
文件有可能出現空洞,但是卻不佔盤塊。

read 從文件中讀數據
write 從文件中寫數據

文件共享 dup dup2
進程:
每一個進程都有一個記錄項,記錄項中包含一張打開文件描述符表,每個文件描述符佔一項(文件描述符標誌,指向文件表項的指針)。
內核爲所有打開文件維持一張文件表( 文件狀態標誌, 當前文件偏移量,指向該文件V節點表項的指針)
每個打開文件都有一個v節點結構(包含文件i節點)i節點包括文件長度,指向盤塊,所有者)、

原子操作:
pread(int fd, buf, bytes, offset)
pwrite(int fd, bud, butes, offset)
相當於調用lseek 再調用 read write
文件共享, 複製一個現有的文件描述符;
dup(fd) 返回一個最小的當前文件描述符 相當於fcntl(fd, F_DUPFD,0)
dup2(fd1, fd2) 可以用fd2參數指定文件描述符, 如果fd2已經打開,先關閉, 如果fd 等於fd2 ,則不關閉,直接返回 否則FD_CLOEXEC文件描述標誌就被清除,這樣fd2在進程調用exec是打開狀態 相當於 fcntl(fd, F_DUPFD, fd2)

 不同exec來模擬 dup2
#include "apue.h"
#include "apueerror.h"
#include <fcntl.h>
#include <stdio.h>
#include <stdbool.h>
#define MAX_OPEN
bool mydup2(int fd, int newfd){
     //檢測fd 時候有效
     if(fd < 0 || fd >MAX_OPEN){
        printf("fd is wrong!");
        return false;
     }
     //檢測newfd 時候有效
     if(newfd < 0 || newfd > MAX_OPEN){
        printf("newfd is wrong!");
        return false;
     }

     int queue[newfd + 10];
     //檢測fd 是否是打開狀態
     if((queue[fd] = dup(fd)) != -1){
        printf("error");
        return false;
     }else{
        if(newfd == fd) return true;
        int i = 0;
       close(newfd);
       for(i = 0; i <= newfd; i++){
          queue[i] = dup(fd);
       if(queue[i] == -1)  {
          printf("open already!");
          continue;
       }else {

          if(queue[i] == newfd){
             printf("%d!\n",i);
             break;
           }
            queue[i] = MAX_OPEN + 1;
       }
     }
    int j = 0;
    將多打開的關閉掉
    for( j = 0; j < i; j++){
      if(queue[j] == MAX_OPEN + 1)
         close(queue[j]);
    }
   return true;
}

sync, sync, fdatasync

當我們向文件讀寫數據時,內核通常線將數據複製到緩衝區,然後排入隊列,玩些時候再卸入磁盤,
sync(fd)將修改過的所有塊緩衝區排入寫隊列, 然後返回, 不等待時機磁盤寫操作完成。
fsync(fd)函數支隊有文件 描述符fd指定的文件起作用,並且等待寫操作完成後才返回。(數據屬性都可以更新)
fdatasync()函數類似於 sync, 但他隻影響文件的數據部分,

fcntl(fd, cmd …)
複製一個已有文件的描述符 F_DUPFD/ F_DUPFD_CLOEXEC
獲取/設置文件描述標誌 F _GETFD/ F_SETFD
獲取/設置文件狀態標誌 F_GETFL/ F_SETFL
獲取/設置文件異步i/o所有權 F_GETOWN/ F_SETOWN
獲取/設置記錄鎖 F_GETTLK, GE_SETTLK, F_SETLKW

文件和目錄
int stat(pathname, stat *buf)
int fstat(fd,stat * buf)
int lstat(pathname, stat*buf)
int fstatat(fd, pathname, struct *buf, flag)

stat 返回於與pathname命名文件的有關信息
lstat 獲得fd上打開的文件信息, 但是當命名的文件是一個符號鏈接時,返回改符號的有關信息。
fstatat 當一個相對目錄打開時,返回文件統計信息。 flag 爲 AT_SYMLINK_NOFOLLOW 標誌被設置時 fstatat 不會跟隨鏈接,而是返回器本身信息。 如果 fd 的值時 AT_FDCWD 並且pathname時相對目錄時。  fstatat會計算當前pathname的目錄,
but 是一個指向 stat  結構體的指針

文件類型 普通文件,目錄文件, 字符特殊文件, 塊特殊文件, fifo。 套接字, 符號鏈接

access(pathname, mode)
faccess(fd, pathname, mode, flag)
如果 flag = AT_EACCESS 訪問檢查的是調用進程的有效用戶id 和有效組id, 而不是實際id

umask 設計文件模式創建屏蔽字並且返回之前的值,
chmod, fchomod., fchomdat 更改現有文件訪問權
chown, fchown, lchown, fchownat, 更改文件的用戶,文件的用戶組
chown(pathname, owner, group)
fchown(fd, pathname, owner, group)
fchownat(fd, pathname, owner, group, flag)
lchown( pathname, owner, group)
如果owner, 或者group又一個爲-1 則不改變 ,
文件截斷
truncate(pathname, off_t length)
ftruncate(fd, length)
階段到 length

link, linkat, unlink, unlinked, remove

符號鏈接
指對一個文件的簡介指針, 硬鏈接直接指向 文件的i節點, 引入符號鏈接的原因是爲了避免硬鏈接的一些限制 (硬鏈接要就鏈接和文件位於一個文件系統, 只有超級用戶才能創建硬鏈接)
創建和讀取符號鏈接
symlink symlinat
int symlink(acpathname, sympath)
int symlinkat(acpahtname, fd, sympath)
創建了一個指向 actualpaht 的新目錄項 sympaht , 並不要求actualpath已經存在,

發佈了448 篇原創文章 · 獲贊 3 · 訪問量 14萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章