Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
What is fopen() and open() in Linux?
The key difference between fopen() and open() in Linux is that open() is a low-level system call that returns a file descriptor (integer), while fopen() is a higher-level C library function that internally calls open() and returns a FILE pointer with additional buffering capabilities.
Understanding open() System Call
When you call open(), it invokes the kernel's sys_open() function, which performs several operations to establish the file connection. Here's the simplified implementation:
int sys_open(const char *filename, int flags, int mode) {
char *tmp = getname(filename);
int fd = get_unused_fd();
struct file *f = filp_open(tmp, flags, mode);
fd_install(fd, f);
putname(tmp);
return fd;
}
This code can be found in the fs/open.c file on your Linux system.
Step-by-Step Execution
1. getname() Function
The getname() function copies the filename from user space to kernel space:
#define __getname() kmem_cache_alloc(names_cachep, SLAB_KERNEL)
#define putname(name) kmem_cache_free(names_cachep, (void *)(name))
char *getname(const char *filename) {
char *tmp = __getname(); /* allocate some memory */
strncpy_from_user(tmp, filename, PATH_MAX + 1);
return tmp;
}
This function is located in fs/namei.c and handles the transition from user space to kernel space.
2. get_unused_fd() Function
The get_unused_fd() function returns an unused file descriptor ? an integer index into the process's file table:
int get_unused_fd(void) {
struct files_struct *files = current->files;
int fd = find_next_zero_bit(files->open_fds, files->max_fdset, files->next_fd);
FD_SET(fd, files->open_fds); /* mark as in use */
files->next_fd = fd + 1;
return fd;
}
3. filp_open() Function
The filp_open() function performs two critical tasks:
struct file *filp_open(const char *filename, int flags, int mode) {
struct nameidata nd;
open_namei(filename, flags, mode, &nd);
return dentry_open(nd.dentry, nd.mnt, flags);
}
First, it uses the filesystem to look up the inode corresponding to the filename. Then, it creates a struct file containing essential information about the inode and returns it.
4. fd_install() Function
The fd_install() function stores the file structure in the process's file descriptor table:
void fd_install(unsigned int fd, struct file *file) {
struct files_struct *files = current->files;
files->fd[fd] = file;
}
This function can be found in include/linux/file.h.
Comparison
| Aspect | open() | fopen() |
|---|---|---|
| Level | System call (low-level) | C library function (high-level) |
| Return Type | File descriptor (int) | FILE pointer (FILE*) |
| Buffering | No buffering | Built-in buffering |
| Performance | Faster (direct system call) | Slower (additional overhead) |
| Portability | UNIX/Linux specific | ANSI C standard (portable) |
Conclusion
The open() function is a low-level system call that directly interfaces with the kernel, while fopen() is a higher-level wrapper that provides additional features like buffering. Understanding the internal workings of open() reveals the complex kernel operations involved in file access, including memory allocation, file descriptor management, and inode lookup.
