日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

Linux命令【四】文件+虚拟内存+常用系统函数

發布時間:2023/11/30 linux 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux命令【四】文件+虚拟内存+常用系统函数 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

File*其實是一個結構體

  • 文件描述符FD:索引到對應的磁盤文件
  • 文件讀寫位置指針FP_POS,如果同時讀寫需要注意文件指針的位置
  • I/O緩沖區BUFFER:保存內存指針,默認大小是8kb,用于減小我們對硬盤操作的次數。因為我們對硬盤的操作是ms級別的,而我們電子設備的操作是ns級別的。
  • 刷新緩沖區到硬盤上:fflush、緩沖區已滿、文件正常關閉、return main、exit main
  • Linux系統函數沒有緩沖區,C庫函數自帶緩存

在Linux中,inode保存文件的屬性,里面有一個結構體struct stat,其中記錄了文件的各種信息,但是沒有保存文件名。
文件名保存在denty(目錄項)中,每一個文件名對應一個inode編號。每一個硬鏈接都是一個denty

以Linux32為系統為例:

  • 文件描述符:
    • Linux為每一個運行的程序分配0-4G的內存
    • 0-3G是用戶區,3-4G是內核區,內核區不允許用戶去訪問
    • 文件描述符位于內核區中的PCB進程控制塊中,0-1023,每個位置儲存一個文件。0\1\2默認是打開的,分別是STDIN_FiLENO 、STDOUT_FILENO 、STDERR_FILENO,每打開一個新文件,會多儲存一個文件描述符。是一個棧

查看文件格式:file 文件

虛擬地址

用戶區:0-3G

  • 受保護的內存(0-4K)none指針指向這個位置
  • ELF段
    • .text 代碼段,二進制機器指令,包含main函數、靜態庫
    • .rodata段 和.text一樣都是ro(只讀)權限,在鏈接的時候完成數據段合并
    • .data段 已經初始化的全局變量
    • .bss未初始化的全局變量,和.data段一樣是rw(讀寫)權限
  • 堆空間:保存全局變量,用malloc或者new在堆上分配內存
  • 共享庫: 動態庫,對庫的調用是相對的地址。
  • 棧空間:從上面開始分配內存,保存局部變量
  • 命令行參數:main函數的參數
  • 環境變量:env查看

CPU使用虛擬地址與物理空間映射的作用:

  • 方便編譯器和操作系統安排程序的地址分布:程序可以使用一系列連續的虛擬地址訪問內存中不連續的內存緩沖區
  • 方便進程之間的隔離:不同進程之間彼此隔離,一個進程中的代碼無法更改正在另一項進程的物理內存
  • 方便OS使用內存:程序可以使用一系列虛擬地址來訪問大于可用物理內存的內存緩沖區。當物理內存的供應量變小時,內存管理器會將物理內存頁(通常為4KB)保存到此案文件。數據或代碼頁會根據需要在物理內存和磁盤之間移動

printf函數

printf函數
調用write函數將文件描述符傳遞
應用層運行write函數
系統調用sys_write()函數,從用戶態轉化為內核態
內核層設備驅動函數

常用的系統應用函數

man 章節號 需要查找的函數 // 查看Linux手冊中的函數

open函數

int open(const char *pathname, int flags);// The argument flags must include one of the following access modes: O_RDONLY, O_WRONLY, or O_RDWR. These request opening the file read-only, write-only,or read/write, respectively.int open(const char *pathname, int flags, mode_t mode); //mode:給創建文件設定訪問權限

返回一個文件描述符,-1意思是發生了錯誤,errno會被賦予錯誤信息,使用需要包含errno.h

錯誤宏定義的位置:
第1-34個錯誤:usr/incclude/asm-generic/errno-base.h
第35-133個錯誤:/usr/include/asm-generic/errno.h

void perror(const char *s)用來將上一個函數發生錯與原因輸出到標準設備

編寫函數的時候可以使用章節+ shift+k查看函數的man文檔

例如:

#include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> //open的頭文件 #include<unistd.h> //close的頭文件 #include<stdlib.h> //exit的頭文件 #include<stdio.h> //perror的頭文件 int main() {int fd; //用于保存文件描述符fd = open("main.c",O_RDWR);if(fd==-1){perror("open file");exit(1);}//創建新文件fd = open("newfile.c",O_RDWR | O_CREAT,777);//實際上文件的屬性是775,因為本地有一個掩碼,給定的權限將會和掩碼有一個取反按位與的操作,實際上相當于減法//nmask獲取本地掩碼printf("新文件的文件描述符:%d\n",fd);//關閉文件int ret = close(fd);if(ret==-1){perror("close file");exit(1);}elseprintf("ret=%d\n",ret);return 0; }

獲取本地掩碼:umask
修改本地掩碼:umask xxxx
O_CREAT需要將掩碼取反再將權限按位與

通過O_CREAT 與O_EXCL和起來使用判斷文件是否已經存在,例如:

#include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> //open的頭文件 #include<unistd.h> //close的頭文件 #include<stdlib.h> //exit的頭文件 #include<stdio.h> //perror的頭文件 int main() {int fd; //用于保存文件描述符 /*fd = open("main.c",O_RDWR);if(fd==-1){perror("open file");exit(1);}//創建新文件fd = open("newfile.c",O_RDWR | O_CREAT,777);//實際上文件的屬性是775,因為本地有一個掩碼,給定的權限將會和掩碼有一個取反按位與的操作,實際上相當于減法//nmask獲取本地掩碼printf("新文件的文件描述符:%d\n",fd); */fd = open("myhelloc.c",O_RDWR|O_CREAT|O_EXCL , 777);if(fd==-1){perror("open file");exit(1);} //關閉文件int ret = close(fd);if(ret==-1){perror("close file");exit(1);}elseprintf("ret=%d\n",ret);return 0; }

文件清空、截斷為0O_TRUNC

一定要注意對返回值做一個判斷,這樣出錯的時候就能知道哪里出錯。

read()

#include <unistd.h>ssize_t read(int fd, void *buf, size_t count);

返回值:

  • -1 讀文件失敗,設置errno
  • 0文件讀取了
  • x 讀取了x個字符

write()

#include <unistd.h> ssize_t write(int fd, const void *buf, size_t count);

lseek()

#include <sys/types.h>#include <unistd.h> off_t lseek(int fd, off_t offset, int whence); whence as follows:SEEK_SETThe file offset is set to offset bytes.SEEK_CURThe file offset is set to its current location plus offset bytes.SEEK_ENDThe file offset is set to the size of the file plus offset bytes.

使用舉例:將一個文件的內容拷貝到另一個文件

#include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> //Open #include<unistd.h> //Close #include<stdlib.h> //exit #include<stdio.h> //perror #include<string.h> #define MAXN 1005 char buffer[MAXN]; //緩沖區 int fd_in,fd_out; //用于保存文件描述符void Open() {fd_in=open("file_in",O_RDONLY);if(fd_in == -1){perror("Open fin:");exit(1);}//fd_out=open("file_out",O_WRONLY | O_CREAT | O_EXCL,0777);fd_out=open("file_out",O_WRONLY | O_CREAT,0644);if(fd_out == -1){perror("Open fout:");exit(1);} }void Close() {int ret=close(fd_in);if(ret==-1){perror("Close fin");exit(1);}if(ret==-1){perror("Close fout");exit(1);} }void Work() {int cnt=read(fd_in,buffer,MAXN);if(-1==cnt){printf("讀取文件失敗");}while(cnt) //沒有讀取到文件末尾{write(fd_out,buffer,cnt);cnt=read(fd_in,buffer,MAXN);} } int main() {Open();Work();Close(); }

經驗:

  • open函數如果使用O_CREAT參數,則需要指定使用權限(八進制數字,需要在權限前面加0),如果只使用O_CREAT和O_RDWR參數配合,如果文件已經存在就會打開之前的文件,不會創建新文件,如果再配合O_EXCL參數,那么如果已經存在文件就會報錯。
  • 文件的實際權限是指定權限減去掩碼
  • 不要眼高手低,即使看起來比較簡單的東西還是需要多動手實踐,才能發現自己的問題

lseek

#include <sys/types.h>#include <unistd.h>off_t lseek(int fd, off_t offset, int whence); lseek() repositions the file offset of the open file description associated with the file descriptor fd to the argument offset according to the direc‐ tive whence as follows:SEEK_SETThe file offset is set to offset bytes.SEEK_CURThe file offset is set to its current location plus offset bytes.SEEK_ENDThe file offset is set to the size of the file plus offset bytes.
  • 獲取文件長度ret=lseek(fd,0,SEEK_END)
  • 文件拓展:只能向后拓展文件,不能向前
int ret=lseek(fd,2000,SEEK_END); //文件拓展需要最后做一次寫操作,隨便寫一點東西就可以 //得到一個空洞文件,先得到預定大小的文件然后使用多線程操作 write(fd,"a",1);

總結

以上是生活随笔為你收集整理的Linux命令【四】文件+虚拟内存+常用系统函数的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。