《Beginning Linux Programming》学习笔记 03:终端和数据管理

《Beginning Linux Programming》学习笔记 03:终端和数据管理

第五章《Terminals》和第六章《Managing Text-Based Screens with curses》意义不大,所以只挑拣了一个典型用例,和同样内容不太多的第七章《数据管理》(略去不常用的 dbm 数据库)放在一起。顺便把标题也改了,毕竟这本书只算入门级的嘛,看完后要学的东西还很多的。

termios 结构体

通过与该结构体相关的函数,例如 int tcgetattr(int fd, struct termios* termios_p)int tcsetattr(int fd, int actions, const struct termios* termios_p),可以改变终端的输入和输出行为。该结构体里面有不少五花八门的咚咚,头都给我看花了,而且很多玩意儿感觉也没什么用——都 21 世纪了,还在纯字符界面里玩花哨,谁鸟你?去其糟粕之后,也许下面这段控制是否回显输入的代码算是真正有用的功能之一,可用于提示用户输入密码:

        struct termios oldTermios;
        struct termios newTermios;
        int infd = fileno(stdin);

        tcgetattr(infd, &oldTermios);
        newTermios = oldTermios;                             // 创建副本,便于用完后恢复初始设置。

        printf("Input password: ");
        newTermios.c_lflag &= ~ECHO;
        tcsetattr(infd, TCSAFLUSH, &newTermios);             // 禁用输入回显。

        char* password = NULL;
        size_t n = 0;
        getline(&password, &n, stdin);                       // 屏幕上应当看不到输入的字符。

        tcsetattr(infd, TCSANOW, &oldTermios);               // 恢复初始设置。
        printf("\nYour password is \"%s\".\n", password);    // 输出刚才“盲打”的内容。
        free(password);
    

管理内存

void* malloc(size_t size)void* calloc(size_t number_of_elements, size_t element_size)void* realloc(void* existing_memory, size_t new_size)void free(void* ptr_to_memory) 已经风骚二十多年了,没什么特别的,除了下面这种初学者易犯的错误:

        p = realloc(p, size * 2);    // 假设前面没有创建 p 的副本。
    

realloc 在成功时返回新内存的地址,老内存被自动释放;失败返回 NULL,老内存不变!也就是说,如果这句代码失败,p 就成了一个空指针,而原先的内存已经无法追踪,从而导致内存泄露!

文件锁

《BLP》讲了三种方式,用起来都非常简单:

  1. 使用函数 int open(const char* path, int oflags, mode_t mode),并带上 O_CREATO_EXCL 标识,来创建锁文件。
  2. 使用函数 int fcntl(int fildes, int command, struct flock* flock_structure) 对文件进行局部锁定。
  3. 使用函数 int lockf(int fildes, int function, off_t size_to_lock) 对文件进行局部锁定。

这三种方式创建的锁都属于“劝告锁”(Advisory Lock)。劝告锁仅仅是进程间的一种“游戏规则”,所以只对按规则出牌的进程起作用。如果有进程不按规矩办事,通过其他方式直接操作被“锁住”的文件,内核并不会阻止。劝告锁需要多个进程的协作才能生效;在同一个进程中,即使在前面加了锁,后面的代码也无法检测出来,加锁操作总是会成功。劝告锁很有画地为牢的感觉……

要想彻底锁住文件,必须使用“强制锁”(Mandatory Lock),《BLP》没有讲。上网搜了一下,步骤是:

  1. 使用 -o mand 选项挂载文件系统。强制锁必须要得到文件系统支持才能生效。
  2. 修改要加锁的文件的权限:设置 SGID 位,并清除组可执行位。
  3. 使用 fcntl 对文件进行加锁或解锁,步骤和劝告锁相同。

强制锁不是 POSIX 兼容的,而且由于 Linux 无法解决某些竞争条件,使得它不可靠。详见 Linux 内核文档“mandatory-locking.txt”,注意其中的第 0 个问答就是“Why you should avoid mandatory locking”。

你可能感兴趣的:(《Beginning Linux Programming》学习笔记 03:终端和数据管理)