Linux文件操作---隨手記

文件定義

狹義

磁盤文件,進而可以是有組織有次序地存儲在任何介質(包括內存)中的一組信息

廣義

凡是可以產生或者消耗信息的都是文件。(也包括socket)

文件操作方式

系統調用 庫函數
open fopen
read fread
write fwrite
close fclose
lseek, ioctl… fseek, fgetc, fputc…

系統調用:linux system call 類似windows 的api,爲linux特有的系統操作,其中有關文件的操作有:pen, read, write, close, lseek, ioctl, 等
庫函數:庫函數是編程語言提供的函數集合,比如C的標準輸入輸出庫:stdio.h 提供了以下函數fopen, fread, fwrite, fclose, fflush fseek, etc.
,這些函數不侷限於linux操作系統,其他支持該C標準庫的操作系統同樣可以使用。
在linux 中,庫函數對文件的操作實際是對系統調用的相關操作的封裝。

創建

系統調用 參數
Int creat(const char *filename,mode_t mode) 參數mode指定新建文件的讀寫權限,與umask共同決定文件的最終權限。Umask代表文件創建時去掉默寫讀寫權限,可通過系統調用 int umask(int newmask)修改

打開

系統調用

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

例子

open(“test”, O_CREAT, 10705)
open(“test”, O_CREAT,  S_IRWXU | S_IROTH | S_IXOTH | S_ISUID)

C庫函數

FILE *fopen(const char *path, const char *mode);
Mode Comment
r,rb 只讀打開
W,wb 只寫打開,文件不存在則創建
a,ab 追加方式打開(只寫),文件不存在則創建
r+,r+b,rb+ 讀寫方式打開
w+,w+b,wh+ 讀寫方式打開,文件不存在則創建
a+,a+b,ab+ 追加讀寫打開,文件不存在則創建

讀寫

系統調用

int read(int fd, const void *buf, size_t length);

從文件描述符fd指定的文件中讀取length個字節到buf緩衝區

int write(int fd, const void *buf, size_t length);

length個字節從buf緩衝區寫入到文件描述符fd指向的文件中

C庫函數

int fgetc(FILE *stream);
int fputc(int c, FILE *stream);
char *fgets(char *s, int n, FILE *stream);
int fputs(const char *s, FILE *stream);
int fprintf(FILE *stream, const char *format, ...);
int fscanf (FILE *stream, const char *format, ...);
Size_t fread(void *ptr, size_t size, size_t n, FILE *stream);
Size_t fwrite (const void *ptr, size_t size, size_t n, FILE *stream);

定位

系統調用

int lseek(int fd, offset_t offset, int whence); 

作用,移動當前讀寫位置,offset含義取決於whence。
返回值:新的偏移量(成功),-1(失敗)

whence offset含義
SEEK_SET 文件偏移量將被設置爲 offset
SEEK_CUR 文件偏移量將被設置爲 cfo (當前文件偏移量)加上 offset
SEEK_END 文件偏移量將被設置爲文件長度加上 offset

技巧:currpos = lseek(fd, 0, SEEK_CUR) 返回當前的文件偏移量

C庫函數

int fgetpos(FILE *stream, fpos_t *pos);
int fsetpos(FILE *stream, const fpos_t *pos);
int fseek(FILE *stream, long offset, int whence); 

關閉

系統調用 C庫函數
int close(int fd); int fclose (FILE *stream);

示例——文本複製

系統調用

#include <unistd.h>  
#include <sys/stat.h>  
#include <fcntl.h>  
#include <stdlib.h>  
 
int main()  
{  
    char c = '\0';  
    int in = -1, out = -1;  
    in = open("Data.txt", O_RDONLY);  
    out = open("copy_system.out.txt", O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR);  
    while(read(in, &c, 1) == 1)
         {
            write(out, &c, 1);
         }
    close(in);  
    close(out);  
    return 0;  
}  

C庫函數

#include <stdio.h>  
#include <stdlib.h>  
  
int main()  
{  
    int c = 0;  
    FILE *pfin = NULL;  
    FILE *pfout = NULL;  
     pfin = fopen("Data.txt""r");  
    pfout = fopen("copy_stdio.out.txt""w");     
    while(fread(&c, sizeof(char), 1, pfin))
{
        fwrite(&c, sizeof(char), 1, pfout);
}
    fclose(pfin);  
    fclose(pfout);  
    return 0;  
} 

區別

系統調用(open) C庫函數(fopen)
int open(const char *path, int access,int mode) FILE *fopen(char *filename, char *mode)
非緩衝操作 緩衝操作
返回 文件描述符 返回 文件指針
可用來操作設備文件,套接字,普通文件等 一般只操作普通文件,不能操作設備文件
在linux中由內核實現文件操作 在linux中間接調用系統調用open
只針對linux 多操作系統移植

文件層次

底層上,linux文件系統包括Ext2,等。
向上,則爲用戶程序提供一個統一的,抽象的,虛擬的文件系統界面。也就是所謂的虛擬文件系統-VFS(virtual filesystem ),虛擬文件系統爲用戶程序提供了一組標準的,抽象的文件操作——read ,write,lseek 等。也就是我們所謂的 系統調用。(文件操作包括 系統調用和庫函數)

圖1
這裏寫圖片描述

系統調用open是如何調用驅動的open的

註冊字符設備

file_operations misc_fops = { .open= misc_open};
register_chrdev(MISC_MAJOR,”misc”,&misc_fops)

圖2
這裏寫圖片描述

系統調用open

圖3
這裏寫圖片描述

進程中文件操作的結構

圖4
這裏寫圖片描述

Android中的文件系統

Init.rc中的文件分區與文件屬性

Command Comment
chmod 改變文件訪問權限
chown 改變文件所屬和組
mkdir [mode] [owner] [group] 在創建一個目錄,可選選項:mod,owner,group.如果沒有指定,目錄以755權限,owner爲root,group爲root創建.
mount [ ]* 嘗試mount 到目錄. 可以用mtd@name格式以命名指定一個mtd塊設備。包含”ro”,”rw”,”remount”,”noatime”
write [ ]* 打開的文件並寫入一個或多個字符串。

掛載ROM分區到 /system;/data;/cache 分區:

mount ext4 /dev/block/mmcblk0p9 /system ro wait noatime
mount ext4 /dev/block/mmcblk0p12 /data wait nosuid nodev noatime discard
mount ext4 /dev/block/mmcblk0p8 /cache nosuid nodev noatime journal_async_commit

noatime:Linux缺省每次讀文件,都要更新這個文件的last access time屬性,增加這個noatime選項,則在讀文件時不去更改文件的access time屬性了,提高文件系統性能

文件屬性簡介

Linux文件可以分爲如普通文件、目錄、符號鏈接文件、字符和塊設備文件、套接口文件等。
Umask-代表“剝奪”的權限
Mode 的助記表示法
-R參數循環設置目錄下的所有文件及目錄
setuid和setgid 位-setuid 和 setgid “ ” 是讓程序執行的時候 臨時的 的擁有了程序
文件所有者的 uid 和 gid,等程序執行完後再恢復到發起者的權限。
對於目錄,如果在某個目錄上設置了 setgid 位以後,在這個目錄中創建的文件具有該目錄的屬組權限而不是創建該文件的用戶的默認屬組

Sticky粘貼位(較少用到)-一個目錄即使它的所有權限都開放rwxrwxrwx,如果是設置了粘帖位,除非目錄的屬主和root用戶有權限刪除它,除此之外其它用戶不能刪除這個目錄,用途一般是把一個文件夾的的權限都打開,然後來共享文件,象/tmp目錄一樣。

命令 ls -lih
顯示結果 699679673 -rw-r–r– 1 xxxxx xxxxx 681 2013-05-24 09:16 Android.mk
顯示結果 688685627 -rw-r–r– 1 xxxxx xxxxx 0 2013-05-24 11:02 Version.inc
涵義(一一對應) Inode;文件種類和權限;硬鏈接個數;User;Group;大小;最後訪問/修改時間;文件/目錄名
技巧 上面的Version.inc顯示有一個硬鏈接,通過find -inum 688685627可以查找對應硬鏈接文件,結果另一個文件位於./vendor/Version.inc

Android文件系統的初始權限

tmpfs文件系統類型是基於虛擬內存的文件系統
rootfs,也是一種基於RAM的文件系統,可以看到Android的/是直接建立在RAM上的

android/system/core/include/private/android_filesystem_config.h
定義了各個用戶及用戶組,並定義了部分目錄的用戶,用戶組,讀寫權限

Android 系統編譯時會使用兩個 Android 命令 mkbootfs 和 mkyaffs2image 來生成這些 img文件,這兩個命令都會調用文件 android_filesystem_config.h 中預製的權限,來寫入這些目錄和文件資源初始的訪問權限


#define AID_ROOT             0
#define AID_SYSTEM        1000
#define AID_RADIO         1001
…………………………

static struct fs_path_config android_dirs[] = {
    { 00770, AID_SYSTEM, AID_CACHE,  "cache" },
    { 00771, AID_SYSTEM, AID_SYSTEM, "data/app" },
    { 00771, AID_SYSTEM, AID_SYSTEM, "data/app-private" },
    { 00771, AID_SYSTEM, AID_SYSTEM, "data/dalvik-cache" },
    { 00771, AID_SYSTEM, AID_SYSTEM, "data/data" },
    //可以在此處添加新增目錄的權限

分別對應:Mode uid gid *prefix


static const struct android_id_info android_ids[] = {
    { "root",      AID_ROOT, },
    { "system",    AID_SYSTEM, },
    { "radio",     AID_RADIO, },
 …………………………

分別對應Name和aid


static struct fs_path_config android_files[] = {
    { 00440, AID_ROOT,      AID_SHELL,     "system/etc/init.goldfish.rc" },
    { 00550, AID_ROOT,      AID_SHELL,     "system/etc/init.goldfish.sh" },
    { 00440, AID_ROOT,      AID_SHELL,     "system/etc/init.trout.rc" },
    { 00550, AID_ROOT,      AID_SHELL,     "system/etc/init.ril" },
    //可以在此處添加新增文件的權限

分別對應:Mode uid gid *prefix

新增設備權限

android/system/core/rootdir/ueventd.rc

/dev/null                 0666   root       root
/dev/zero                 0666   root       root
/dev/full                 0666   root       root
/dev/ptmx                 0666   root       root
/dev/tty                  0666   root       root
/dev/random               0666   root       root
/dev/urandom              0666   root       root
/dev/ashmem               0666   root       root
/dev/binder               0666   root       root
新增設備時在此文件中添加權限

對於新添加的設備,需要在該文件中添加對應的設備權限,否則可能出現無法使用的情況。

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