学习stty
设备文件
设备文件名使用ls /dev
命令在/dev
中查看
终端就像文件
设备文件与磁盘文件的区别
- 常用的磁盘文件由字节组成,磁盘文件中的字节数就是文件的大小。而对于设备文件而言,其i节点指向的是对应的设备驱动程序指针,当应用程序对设备文件进行读写操作时,内核会根据i节点,调用相应的内核子程序来执行实际的设备操作。
- 进程到磁盘的字节会先被缓冲,然后才从内核的缓冲区发送出去,而进程需要尽快把到设备文件的数据传送出去。
磁盘文件属性
通过fcntl
修改缓冲属性
1 2 3 4 5 6 7
| #include <fcntl.h> int s; s = fcntl(fs, F_GETFL); s |= O_SYNC; if(fcntl(fd, F_SETFL, s) == -1){ perror("setting SYNC error"); }
|
参数F_GETFL用于得到当前的位集,O_SYNC位用于告诉内核对write的调用只能在数据写入实际的硬件是才能返回,而不是数据复制到缓冲区就返回,这样可以保证数据一定被写入
自动添加append
模式
当文件描述符的O_APPEND
位被开启后,每个对write的调用将自动调用lseek将内容添加到文件的末尾,并且可以保证多进程同时写入时,不会出现死锁或错误写入。
设备文件属性
使用stty命令改变驱动属性
1 2 3 4
| stty erase X stty -echo stty echo stty erase @ echo
|
通过程序改变驱动属性
- 从驱动程序获得属性
- 修改所要修改的属性
- 将修改过的属性送回驱动程序
termios structure
1 2 3 4 5
| tcflag_t c_iflag; tcflag_t c_oflag; tcflag_t c_cflag; tcflag_t c_lflag; cc_t c_cc[NCCS];
|
1 2 3 4 5
| #include <termios.h> struct termios attribs; tcgetattr(fd, &settings); settings.c_lflag |= ECHO; tcsetattr(fd, TCSANOW, &settings);
|
除了TCSANOW
以外,还有
tips
homework
link是可以用来给文件上锁的,但现如今已被淘汰
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
| #include <stdio.h> #include <unistd.h> #include <errno.h> #include <sys/types.h>
int LockPasswd(){ int rv = 0; if(link("./test.txt", "./test_link.txt") == -1) rv = errno; return rv; }
int main() { pid_t pid = fork();
if (pid < 0) { perror("无法创建子进程"); return 1; } else if (pid == 0) { int result = LockPasswd(); printf("子进程执行结果:%d\n", result); } else { int result = LockPasswd(); printf("父进程执行结果:%d\n", result); }
return 0; }
|
结果如图
使用O_SYNC测试
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
| #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <unistd.h> #include <time.h>
#define BUFFER_SIZE 1024
const char* input_file = "./sync_exp/input"; const char* output_dir = "./sync_exp/output";
void split_file() { int in_fd = open(input_file, O_RDONLY); if (in_fd == -1) { perror("Failed to open input file"); return; }
unsigned char buffer[BUFFER_SIZE]; int cnt = 0;
while((read(in_fd, buffer, BUFFER_SIZE)) != 0){ char output_file[100]; sprintf(output_file, "./sync_exp/output/%d", cnt++); int out_fd = open(output_file, O_WRONLY | O_CREAT | 0777); if (out_fd == -1) { perror("Failed to create output file"); return; }
write(out_fd, buffer, BUFFER_SIZE); close(out_fd); }
close(in_fd); }
int main() { clock_t start = clock(); split_file(); clock_t end = clock(); double time_taken = (double)(end - start) / CLOCKS_PER_SEC; printf("time cost: %f\n", time_taken); return 0; }
|
开启缓冲的结果
关闭缓冲的结果
结论
在1G的input文件轰炸下,关闭缓冲仍然不会太明显地影响速度,可能这就和linux内核实现有关了