学习stty
设备文件
设备文件名使用ls /dev
命令在/dev
中查看
终端就像文件
设备文件与磁盘文件的区别
- 常用的磁盘文件由字节组成,磁盘文件中的字节数就是文件的大小。而对于设备文件而言,其i节点指向的是对应的设备驱动程序指针,当应用程序对设备文件进行读写操作时,内核会根据i节点,调用相应的内核子程序来执行实际的设备操作。
- 进程到磁盘的字节会先被缓冲,然后才从内核的缓冲区发送出去,而进程需要尽快把到设备文件的数据传送出去。
磁盘文件属性
通过fcntl
修改缓冲属性
#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命令改变驱动属性
stty erase X # make 'X' the erase key
stty -echo # type invisibly
stty echo # type visibly
stty erase @ echo # mutiple cmds
通过程序改变驱动属性
- 从驱动程序获得属性
- 修改所要修改的属性
- 将修改过的属性送回驱动程序
termios structure
tcflag_t c_iflag; /* input modes */
tcflag_t c_oflag; /* output modes */
tcflag_t c_cflag; /* control modes */
tcflag_t c_lflag; /* local modes */
cc_t c_cc[NCCS]; /* special characters */
#include <termios.h>
struct termios attribs;
tcgetattr(fd, &settings);
settings.c_lflag |= ECHO;
tcsetattr(fd, TCSANOW, &settings);
除了TCSANOW
以外,还有
tips
homework
link是可以用来给文件上锁的,但现如今已被淘汰
/* 测试两个进程同时创建硬链接,可以得知系统调用link可以起到给文件上锁的作用 */
#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测试
#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内核实现有关了