day06 文件读写位置、文件映射、文件元数据获取

来源:互联网 发布:淘宝送优酷会员 编辑:程序博客网 时间:2024/05/17 00:53
回忆昨天内容:
一、进程映射(续)

二、使用mmap映射物理内存到进程的虚拟地址空间
三、malloc的缓冲机制
brk(2)、sbrk(2)
四、使用系统调用进行文件的操作
open(2)  close(2) read(2)  write(2)

今天的内容:
一、文件读写位置的操作
如何获取文件的读写位置?ftell(3)
如何操作文件的读写位置?使用lseek(2)
#include <sys/types.h>
#include <unistd.h>
off_t  lseek(int  fd,off_t  offset,int whence);
功能:重新定位文件的读写位置
参数:
fd:open(2)的返回值,指定了文件
offset:相对于whence参数的偏移
whence:
SEEK_SET   文件头部
SEEK_CUR   文件的当前位置
SEEK_END   文件尾部
返回值:
-1   错误  errno被设置
返回相对于文件头部的偏移字节数。
举例验证lseek(2)的使用。
代码参见lseek.c
od -tx1 -tc hello
0000000  68  65  6c  6c  6f  20  77  6f  72  6c  64  0a
          h   e   l   l   o       w   o   r   l   d  \n

二、使用mmap将文件映射到进程的虚拟地址空间,对内存的操作,直接反应到文件中。
举例验证,使用mmap将文件映射到进程的虚拟地址空间。对虚拟地址空间里的内容操作,直接反应到文件

代码参见  mmap_file.c
day06$od -tx1 -tc hello
0000000  68  65  6c  6c  6f  0a
          h   e   l   l   o  \n
0000006
day06$a.out hello
success...
day06$od -tx1 -tc hello
0000000  33  32  31  30  6f  0a
          3   2   1   0   o  \n
0000006


三、获取文件的元数据
什么是文件的元数据?
文件的元数据就是文件的属性。
-rw-rw-r-- 1 tarena tarena  561  3月 22 11:08 mmap_file.c

如何查看一个文件的元数据?
stat filename   
day06$stat mmap_file.c
  文件:"mmap_file.c"
  大小:561           块:8          IO 块:4096   普通文件
设备:808h/2056d    Inode:925344      硬链接:1
权限:(0664/-rw-rw-r--)  Uid:( 1000/  tarena)   Gid:( 1000/  tarena)
最近访问:2017-03-22 11:08:48.669454022 +0800
最近更改:2017-03-22 11:08:47.497448544 +0800
最近改动:2017-03-22 11:08:47.545448723 +0800
创建时间:-

每个文件有且仅有一个对应的inode。inode中存储了文件的元数据和文件数据的数据块的编号。
硬链接文件。两个文件的inode是同一个,这样的两个文件称为硬链接文件。
如何创建一个文件的硬链接文件?
day06$ls -l hello
-rw-rw-r-- 1 tarena tarena 6  3月 22 10:26 hello
day06$ln hello ha
day06$ls -l hello
-rw-rw-r-- 2 tarena tarena 6  3月 22 10:26 hello
day06$ls -l ha
-rw-rw-r-- 2 tarena tarena 6  3月 22 10:26 ha

day06$stat ha
  文件:"ha"
  大小:6             块:8          IO 块:4096   普通文件
设备:808h/2056d    Inode:925346      硬链接:2
权限:(0664/-rw-rw-r--)  Uid:( 1000/  tarena)   Gid:( 1000/  tarena)
最近访问:2017-03-22 11:28:12.215223974 +0800
最近更改:2017-03-22 10:26:52.796979272 +0800
最近改动:2017-03-22 11:28:11.051220111 +0800
创建时间:-
文件:"hello"
  大小:6             块:8          IO 块:4096   普通文件
设备:808h/2056d    Inode:925346      硬链接:2
权限:(0664/-rw-rw-r--)  Uid:( 1000/  tarena)   Gid:( 1000/  tarena)
最近访问:2017-03-22 11:28:12.215223974 +0800
最近更改:2017-03-22 10:26:52.796979272 +0800
最近改动:2017-03-22 11:28:11.051220111 +0800
创建时间:-

软链接的建立
day06$ls -l ha
-rw-rw-r-- 1 tarena tarena 6  3月 22 10:26 ha
day06$ln -s ha hb
day06$ls -l h*
-rw-rw-r-- 1 tarena tarena 6  3月 22 10:26 ha
lrwxrwxrwx 1 tarena tarena 2  3月 22 11:35 hb -> ha
day06$cat ha
3210o
day06$cat hb
3210o

day06$stat hb
  文件:"hb" -> "ha"
  大小:2             块:0          IO 块:4096   符号链接
设备:808h/2056d    Inode:925342      硬链接:1
权限:(0777/lrwxrwxrwx)  Uid:( 1000/  tarena)   Gid:( 1000/  tarena)
最近访问:2017-03-22 11:35:40.293448722 +0800
最近更改:2017-03-22 11:35:39.277447350 +0800
最近改动:2017-03-22 11:35:39.277447350 +0800
创建时间:-

day06$ln ha hello
day06$rm ha
day06$cat hb
cat: hb: 没有那个文件或目录

如何获取一个文件的元数据?
使用系统调用stat(2)获取文件的元数据。
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int stat(const char *path, struct stat *buf);
功能:获取文件的状态信息
参数:
path:指定了文件的名字
buf:将文件的状态信息存储到buf指定的空间里。

struct stat{
    dev_t   st_dev;  /* ID of device containing file */
        ino_t   st_ino;     /* inode number */
        mode_t  st_mode;    /* protection */
        nlink_t st_nlink;   /* number of hard links */
        uid_t   st_uid;     /* user ID of owner */
        gid_t   st_gid;     /* group ID of owner */
        dev_t   st_rdev;    /* device ID (if special file) */
        off_t   st_size;    /* total size, in bytes */
    blksize_t st_blksize; /* blocksize for file system I/O */
        blkcnt_t  st_blocks;  /* number of 512B blocks allocated */
        time_t    st_atime;   /* time of last access */
        time_t    st_mtime;   /* time of last modification */
        time_t    st_ctime;   /* time of last status change */
};

返回值:
-1  错误   errno被设置
0  成功

举例验证,获取文件的元数据,并将其输出到显示器。
代码参见mystat.c

补充:
1、如何将uid的数字转换为用户的名字?
getpwuid(3)
#include <sys/types.h>
#include <pwd.h>
struct passwd *getpwuid(uid_t uid);
功能:获取用户的信息
参数:
uid:指定用户的uid
返回值:
返回一个指向struct passwd结构体的指针
NULL 找不到这个用户的信息或错误产生 如果是产生错误,errno被设置

2、/etc/passwd文件的内容
这个文件里存放的是系统的所有用户的信息。
tarena:x:1000:1000:tarena,,,:/home/tarena:/bin/bash
struct passwd {
       char   *pw_name;       /* username */
       char   *pw_passwd;     /* user password */
       uid_t   pw_uid;        /* user ID */
       gid_t   pw_gid;        /* group ID */
       char   *pw_gecos;      /* user information */
       char   *pw_dir;        /* home directory */
       char   *pw_shell;      /* shell program */
};
3、如何通过gid获取组名?
getgrnam(3)
getgrgid(3)
#include <sys/types.h>
#include <grp.h>
struct group *getgrgid(gid_t gid);
功能:获取一条组信息
参数:
gid:指定的组id
struct group{
           char   *gr_name;       /* group name */
               char   *gr_passwd;     /* group password */
               gid_t   gr_gid;        /* group ID */
               char  **gr_mem;        /* group members */
};

返回值:
返回一个指向struct group结构体的指针
NULL 找不到这个组的信息或错误产生 如果是产生错误,errno被设置
4、组信息存放在/etc/group文件中
tarena:x:1000:

5、将长整型的时间转换为字符串格式的时间
ctime(3)
#include <time.h>
char *ctime(const time_t *timep);
功能:将长整型的时间转换为字符串格式
参数:
timep:长整型的时间
返回值:
NULL   错误
字符串

作业解决:
char *mystrcpy(char *dest, const char *src);

总结:
一、lseek文件读写位置的定位
二、使用mmap将文件映射到进程的虚拟地址空间,对内存的操作直接反应到文件里。
三、获取文件的元数据

作业:编写代码实现ls -l filename的功能,生成可执行文件myls

myls filename