磁盘文件,进而可以是有组织有次序地存储在任何介质(包括内存)中的一组信息
凡是可以产生或者消耗信息的都是文件。(也包括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)
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指向的文件中
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) 返回当前的文件偏移量
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;
}
#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
file_operations misc_fops = { .open= misc_open};
register_chrdev(MISC_MAJOR,”misc”,&misc_fops)
图2
图3
图4
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 [ ]* | 打开的文件并写入一个或多个字符串。 |
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 |
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
新增设备时在此文件中添加权限
对于新添加的设备,需要在该文件中添加对应的设备权限,否则可能出现无法使用的情况。