虚拟地址空间原理
学习视频
Linux 为每个运行程序(进程) 操作系统都会为其分配一个 0 ~ 4G 的地址空间 (虚拟地址空间)
- 进程: 正在运行的程序
- Linux 下 可执行文件格式: ELF
- 格式主要包含3个段
- 其他段:
- 只读数据段
- 符号段
- 通过这一节,你应该知道,一个内存管理系统至少应该做三件事情:
- 第一,虚拟内存空间的管理,每个进程看到的是独立的、互不干扰的虚拟地址空间;
- 第二,物理内存的管理,物理内存地址只有内存管理模块能够使用;
- 第三,内存映射,需要将虚拟内存和物理内存映射、关联起来。
linux 文件读写 API
学习视频
目录操作
- 目录操作
opendir
readdir
closedir
cpp 的 api
- 函数
open
close
read
write
lseek
文件描述符
文件描述符和进程的原理
每一个进程都有一个 PCB 【进程控制块】
-
进程控制块里面有一个 文件描述符表
-
文件描述符表 是基于一个 长度为 1024的数组俩实现的
-
前3个文件描述符 分别是
1. 0 表示 表示输入
2. 1 表示标准输出
3. 2 表示标准错误输出
4. 其他的话待定
1. 一般就是 调用 open 函数 就会返回一个 fd
1. 这个 fd 就存在 PCB 的文件描述符表数组里面
-
前3个默认被占用,后面的 是给 系统打开文件的 api 存 fd 用
- 每打开一个新文件就占用一个文件描述符【而且使用的是空闲的最小的一个文件描述符】
open函数解释
-
open/close
- 函数原型:
- int open(const char* pathname, int flags);
- int open(const char* pathname,int flags, mode_t mode);
- 参数:
- flags:
- 必选项: O_RDONLY, O_WRONLY, O_RDWR
- 可选:
- 创建文件: O_CREAT
- 如果文件存在, 返回 -1
- 追加文件: O_APPEND
- 文件截断: O_TRUNC
- 设置非阻塞: O_NONBLOCK
- mode
-
read
- 函数原型: ssize_t read(int fd,void* buf, size_t count);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <cstdio>
#include <unistd.h>
using namespace std;
int main(void) {
int fd = -1;
fd = open("app.txt",O_RDWR|O_CREAT, 0777);//读,写执行
if (fd == -1 ) {
puts("打开文件失败");
// exit(1);
}
close(fd);
puts("打开文件成功");
return 0;
}
/*
-rwxrwxr-x 1 lyr lyr 0 Sep 24 22:20 app.txt
最后的结果其实是 775 不是 777
因为 他的结果其实是 mode & ~umask
这个是 linux 给的一个保护作用
umask 输出 其实是 0002
0002 + 775 = 777
*/
|
文件操作相关的函数
根据文件描述符来操作文件的状态 – #include <fcntl.h>
函数原型
int fcntl(int fd, int cmd);
int fcntl(int fd, int cmd, long arg);
int fcntl(int fd, int cmd, struct flock *lock);
复制一个现有的描述符 – cmd
F_DUPFD
获得/设置文件描述符标记 – cmd
F_GETFD
F_SETFD
获得/设置文件状态标记 – cmd
F_GETFL
只读打开
O_RDONLY
只写打开
O_WRONLY
读写打开
O_RDWR
执行打开
O_EXEC
搜索打开目录
O_SEARCH
追加写
O_APPEND
非阻塞模式
O_NONBLOCK
F_SETFL
可更改的几个标识
O_APPEND
O_NONBLOCK
获得/设置异步I/O所有权 – cmd
F_GETOWN
F_SETOWN
获得/设置记录锁 – cmd
F_GETLK
F_SETLK
F_SETLKW
阻塞读取终端数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <cstdio>
#include <cstdlib>
using namespace std;
int main(void) {
#define N 45
char buf[N];
int n;
n = read(STDIN_FILENO,buf, N);
if( n< 0 ) {
perror("read stdin_error");
exit(1);
}
write(STDOUT_FILENO,buf, n);
return 0;
}
|
非阻塞读取数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cerrno>
using namespace std;
#define MSG_TRY "try to read s:=\n"
int main(void) {
#define BufSize 10
char buf[BufSize];
int fd,n;
//非阻塞读,没读取到数据,立刻返回
fd = open("/dev/tty", O_RDONLY | O_NONBLOCK);
if (fd < 0)
{
perror(" open fail /dev/tty");
exit(1);
}
tryRead:
n = read(fd, buf, BufSize);
if ( n < 0 ) {
if ( errno == EAGAIN) {
sleep(3);
write(STDOUT_FILENO, MSG_TRY, strlen(MSG_TRY));
//重新读取数据
goto tryRead;
}
perror("read /dev/tty");
}
write(STDOUT_FILENO,buf, BufSize);
close(fd );
return 0;
}
|