一、进程映射(续)
堆
二、使用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