回忆昨天课程内容
一、内存管理
进程的映像 代码段 数据段 堆 栈段
变量的空间分配在什么地方,不同的段有不同的属性
变量的生命周期 变量的作用域
堆 手动释放free p=NULL;
进程 pid PCB 进程的映像是属于PCB的一个成员
const 定义一个只读变量
二、使用mmap将物理地址映射到进程的虚拟地址空间
mmap munmap
三、文件的操作
open(2) close(2) read(2) write(2)
文件描述符 进程的pid PCB 可变参数
0标准输入 STDIN_FILENO
1标准输出 STDOUT_FILENO
2标准错误输出 STDERR_FILENO
umask 权限掩码
今天内容
一、lseek(2)
#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);
功能:
参数:
fd 指定了要操作的文件
offset
whence- SEEK_SET offset
The offset is set to offset bytes.
SEEK_CUR locat+offset
The offset is set to its current location plus offset bytes.
SEEK_END 文件的末尾+offset
The offset is set to the size of the file plus offset bytes.
返回值:错误 (offset_t)-1 errno被设置
成功 返回当前位置距离文件开头的字节数
二、使用mmap(2)讲文件映射到进程的虚拟地址空间,对内存进行操作,直接反应到文件
代码参见 map.c
day05$od -tx1 -tc hello
0000000 68 65 6c 6c 6f 20 62 65 69 6a 69 6e 67 0a
h e l l o b e i j i n g \n
0000016
day05$a.out hello
day05$od -tx1 -tc hello
0000000 34 33 32 31 6f 20 62 65 69 6a 69 6e 67 0a
4 3 2 1 o b e i j i n g \n
0000016
高位字节存放在低地址 大端
高位字节存放在高地址 小端
编写程序,测试自己的主机字节序
三、文件描述符的复制
dup(2) dup2(2)
#include <unistd.h>
int dup(int oldfd);
功能:复制一个文件描述符,使用最小的
参数:
oldfd 源描述符
返回值:错误-1 errno被设置
成功:返回新的文件描述符
int dup2(int oldfd, int newfd);
功能:复制一个文件描述符,使用newfd指定的,如果原来的描述符是打开的,将其关闭
参数:
oldfd 源描述符
newfd 目的描述符
返回值:错误 -1 errno被设置
成功 返回newfd
编写代码实现文件输出重定向 代码参见direct.c
四、获取文件的原数据
什么是文件的元数据,文件是怎么存储的?
一个文件包含两个部分内容 元数据和内容
元数据是对一个文件的描述信息
每个文件有且仅有一个inode,且每个inode都有自己的编号
链接文件
软链接
硬链接 文件的inode是同一个
ln 源文件 目标文件 之后两个文件inode相同
stat(2)
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int stat(const char *pathname, struct stat *buf);
功能:获取文件身份信息
参数:
pathname 指定文件的路径,获取这个文件的元数据
buf 指定地址,将文件的元数据存储到buf指定的空间里
返回值:
struct stat?
值-结果参数
struct stat {
dev_t st_dev;
ino_t st_ino;
mode_t st_mode;
nlink_t st_nlink;
uid_t st_uid;
gid_t st_gid;
dev_t st_rdev;
off_t st_size;
blksize_t st_blksize;
blkcnt_t st_blocks;
struct timespec st_atim;
struct timespec st_mtim;
struct timespec st_ctim;
#define st_atime st_atim.tv_sec
#define st_mtime st_mtim.tv_sec
#define st_ctime st_ctim.tv_sec
};
struct timespec{
_time_t tv_sec;
_syscall_slong_t tv_nsec;
};
1970年1月1 0点0分0秒 unix诞生
将秒数转换为字符串
ctime(3)
#include <time.h>
char *ctime(const time_t *timep);
功能:将秒数转换为分开的格式
参数:
timep 秒数
返回值:时间字符串,末尾为换行符
根据uid找到用户的名字
系统中维护着用户的信息,所有用户的信息存放在/etc/passwd文件中
tarena:x:1000:1000:ubuntu,,,:/home/tarena:/bin/bash
nan:x:1000:1000:nan,,,:/home/nan:/bin/bash
root:x:0:0:root:/root:/bin/bash
getpwnam(3)
#include <sys/types.h>
#include <pwd.h>
struct passwd *getpwnam(const char *name);
struct passwd *getpwuid(uid_t uid);
struct passwd {
char *pw_name;
char *pw_passwd;
uid_t pw_uid;
gid_t pw_gid;
char *pw_gecos;
char *pw_dir;
char *pw_shell;
};
getgrnam(3)
#include <sys/types.h>
#include <grp.h>
struct group *getgrnam(const char *name);
struct group {
char *gr_name;
char *gr_passwd;
gid_t gr_gid;
char **gr_mem;
};
根据gid找到用户组的名字
direct.c
#include<t_stdio.h>
#include<t_file.h>
#include<string.h>
int main(int argc,char*argv[]){
char *msg="stupid jerryFeng\n";
//打开文件,以写的方式,文件不存在则创建
//权限为0644,文件存在则清空
int fd=open(argv[1],O_WRONLY|O_CREAT|O_TRUNC,0644);
if(fd==-1)
E_MSG("open",-1);
//将标准输出描述符保存
int s_fd=dup(1);
//将标准输出重新定向到打开的文件
dup2(fd,1);
close(fd);
write(1,msg,strlen(msg));
//恢复标准输出
dup2(s_fd,1);
close(s_fd);
write(1,msg,strlen(msg));
return 0;
}
map.c
#include<t_file.h>
#include<t_stdio.h>
#include<sys/mman.h>
int main(int argc,char* argv[]){
//将文件映射到进程的内存
int prot=PROT_READ|PROT_WRITE;
int flags=MAP_SHARED;
int fd=open(argv[1],O_RDWR);
if(fd==-1)
E_MSG("open",-1);
void *p=mmap(NULL,32,prot,flags,fd,0);
if(p==MAP_FAILED)
E_MSG("mmap",-1);
*((int *)p)=0x31323334;
//解除映射
munmap(p,32);
close(fd);
return 0;
}
s_big.c //看自己的虚拟机是大端还是小端
#include<t_stdio.h>
typedef union{
char c;
short s;
}u_t;
int main(void){
u_t temp;
temp.s=0x0001;
printf("temp.s:%p,%d\n",&temp.s,temp.s);
printf("temp.c:%p,%p\n",&temp.c,temp.c);
temp.c?printf("small\n"):printf("big\n");
return 0;
}
stat.c
#include<t_stdio.h>
#include<t_file.h>
#include<time.h>
#include<pwd.h>
#include<grp.h>
int main(int argc,char *argv[]){
//获取文件的元数据,存储到buf
struct stat buf;
int s=stat(argv[1],&buf);
if(s==-1) E_MSG("stat",-1);
printf("hard links:%u\n",buf.st_nlink);
printf("size:%ld\n",buf.st_size);
printf("inode:%ld\n",buf.st_ino);
printf("mtime:%s",ctime(&buf.st_mtime));
printf("uid:%u\n",buf.st_uid);
printf("username:%s\n",(getpwuid(buf.st_uid))->pw_name);
printf("gid:%u\n",buf.st_gid);
printf("group grname:%s\n",(getgrgid(buf.st_gid))->gr_name);
return 0;
}