open系统调用提供了:打开或创建一个文件或设备的功能。系统调用有两个特征:
1)执行一个系统调用后,应用程序的进程将从用户模式(user mode)转到到了内核模式(kernel mode)。至于系统调用发生的详细流程,这里不用关心。
2)系统调用具有事务的特征,其完成的事情要么就全部成功完成,要么就一点也不做。
在Unix/Linux的操作系统里,文件扮演着非常重要的抽象角色,是系统设计的一个近乎哲学上的原则。文件抽象地代表着一切可以对其进行读/写的东西,而事实上图灵机的工作形式就是对存储介质的读和写,可知文件是一个多么强大的概念。因此,围绕着这个概念,操作系统抽象了对其进行的若干操作,open就是其中的一个。
通常,打开一个文件时,从使用者的角度出发,需要关注的几点有:
1)以何种使用方式来打开文件,譬如:
- 子进程里是否也需要其file descriptor。通过fork产生子进程后,子进程是把父进程的所有file descriptor也继承过来的。而子进程执行execve时,所有从父进程里继承过来的file descriptor也都默认保留着。如果子进程不需要这些file descriptor,当然可以通过close将其关闭,但这样的做法在多线程的环境下,可能会引起race condition:因为在子进程试图想关闭这些file descriptor之前,可能已经有该进程里的其它线程不知不觉间在使用这些file descriptor了。况且,子进程要把从父进程里继承过来的所有file descriptor找出来,也是一件吃力的事。而open提供了一个O_CLOEXEC标志,该标志表示进程在执行execve时就应关闭该file descriptor,因open是系统调用,因此能避免race condition的出现。(关于子进程继承父进程的file descriptor,并与父进程一同使用这些file descriptor的情形,会有些有趣的场景,以后再做分析。)
- 以只读、或是只写、还是既可读又可写的方式来打开文件。