1. open
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* x --- 1
* w --- 2
* r ---- 4
*/
int main(){
int fd = 0;
// 只写
fd = open("temp.txt",O_WRONLY);
// 追加写
fd = open("temp2.txt",O_WRONLY|O_APPEND);
// 只读的方式打开 若不存在 就以权限777创建
// 其实这里是有点小bug的, 0777 要与 umask 相与 详见p48
fd = open("temp3.txt",O_RDONLY|O_CREAT,0777);
}
**
错误信息
这个在之前看unix系统编程实践中总是蒙圈
1
2
3
4
5
6
7
8
9
10
11
int main(){
int fd = 0;
fd = open("temp.txt",O_RDONLY);
// 把errno看为一个操作系统的全局变量即可啦
printf("%d\n",errno);
printf("------------------------\n");
printf("%s\n",strerror(errno));
return 0;
}
2. read
函数原型: ssize_t read(int fd, void *buf, size_t count);
- ssize_t : 有符号的返回数
- 读到 0 时到结尾
- count 缓冲区大小
3. write
函数原型 : ssize_t write(int fd, const void *buf, size_t count);
- const 问题 缓冲区不可变
- count 是实际数据大小 , 跟缓冲区大小无关
返回值暂略, 主要看man 2 page
实现cp命令
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
#include<unistd.h>
#include<sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include<string.h>
int main(int argc,char *argv[]){
char buf[1024];
int n = 0;
int fd1 = open(argv[1],O_RDONLY); // 只读
int fd2 = open(argv[2],O_RDWR|O_CREAT|O_TRUNC,0644); // 读权限肯定有 如果没有就创建 如果有这个文件 trunc 重写为0
while ((n = read(fd1,buf,1024)) != 0)
{
write(fd2,buf,n);
}
close(fd1);
close(fd2);
return 0;
}
perror 问题
- perror(“open argv1 error”); // perror 会根据全局的errno 自动生成错误提示信息 贼方便
- 错误信息:
open argv1 error: No such file or directory
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
int main(int argc,char *argv[]){
char buf[1024];
int n = 0;
int fd1 = open(argv[1],O_RDONLY); // 只读
if ( fd1 == -1){
perror("open argv1 error"); // perror 会根据全局的errno 自动生成错误提示信息 贼方便
exit(1);
}
int fd2 = open(argv[2],O_RDWR|O_CREAT|O_TRUNC,0644); // 读权限肯定有 如果没有就创建 如果有这个文件 trunc 重写为0
if ( fd2== -1){
perror("open argv2 error");
exit(1);
}
while ((n = read(fd1,buf,1024)) != 0)
{
if (n < 0)
{
/* code */
perror(" read error");
break;
}
write(fd2,buf,n);
}
close(fd1);
close(fd2);
return 0;
}
4. 系统调用与库函数 详解缓冲区问题
是不是系统调用一定比缓冲区要快?
不是,在有现成的库函数时,尽量使用库函数。 fget() 与 fput() 对比 write() read()
在fput() 与 write() 都使用1字节的buf情况下,fupt() 比write() 要快一个数量级,fput有一个用户级缓存,详情见p53
5. fcontl
改变文件状态 比如阻塞与非阻塞
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int main(){
int flag = 0;
flag = fcntl(STDIN_FILENO,F_GETFD);
if (flag == -1)
{
perror("fcntl error");
exit(1);
}
// printf("%d",flag); // 0
flag |= O_NONBLOCK; // 调为非阻塞状态 位或
int ret = fcntl(STDIN_FILENO,F_SETFD,flag); // F_SETFD
return 0;
}
6. lseek()
应用场景
文件的读与写 使用的是同一个偏移位置
使用lseek获取,拓展文件大小。
扩展文件大小
返回值
较起始位置的偏移量
函数原型
.int lseek(int fd, off_t offset, int whence);
SEEK_SET
:偏移到文件头+ 设置的偏移量 SEEK_CUR
:偏移到当前位置+设置的偏移量 SEEK_END
:偏移到文件尾置+设置的偏移量
- 代码举例
函数思想其实还是很简单,起始位置由后两个参数决定
1
2
3
4
5
6
int main(){
int fd,ret;
fd = open("03_cp.c",O_RDONLY);
ret = lseek(fd,0,SEEK_END);
printf("%d",ret);
}
7. 传入参数与传入参数
略