UNIX Lecture Notes – Chapter 04

Categories:

Recommended

4.1 Overview

This chapter begins by examining how a program can exercise some control over the connections that it makes with disk files. It describes the data structures used by the kernel to manage open files, and explains how processes can interact with these files. It then explores device files and how they are used and structured, and device drivers and their roles and structures. From there it looks at block and character device file differences, after which it turns to terminals. The remainder of the chapter is then devoted to controlling terminals.

4.2 Open Files

The programs that we have studied so far operate on disk files, which are files that reside, of course, on disks. You are by now well-acquainted with the general model of file I/O: open the file, access it, and close it. Remember that this model works for any kind of file, not just disk files. Here though, we are interested only in disk files.

In this model of file I/O, opening a file returns a reference to an object that can be used to access the file, either for reading or writing. When you use the open() system call, you get a le descriptor in return; when you use the fopen() C standard I/O library call, you get a FILE pointer in return. Either way, you are getting a scalar object (i.e., a small integer or a pointer) that is associated with a hidden (kernel) data structure that allows you to access the file. Here, we will explore how much control we can exercise over the way in which the program is connected to the file.

When a process opens a disk file using the open() system call, the kernel creates a data structure that represents the connection between the process and the file. The returned file descriptor can be used by the process to access the file. A file descriptor is simply an index into a per-process table that the kernel uses to locate that specific data structure. Different versions of UNIX call this data structure different things, and the data structure may have slightly different members from one UNIX variant to another, but the basic members and purpose of the structure are invariant: its most important member is the file pointer, and its purpose is to store the position in the file from which the next operation will take place (whether it is a read or a write.)

This data structure is called a file entry in BSD UNIX and a file structure in Linux. I will call it a file structure in these notes. The connection between a process and a file is completely characterized by the information contained in the file structure. Aside from the file pointer, the kinds of information it typically contains include:

  • whether or not the file is open for reading, writing, reading and writing, or appending,
  • whether or not the I/O is buffered or unbuffered, and
  • whether or not the access is exclusive or whether other processes also access the le.

as well as other information that is required by the kernel. The information contained in the le structure characterizes the connection between the open file and the process; it is specific to this single connection. Other processes might have this le open with different attributes. Many of the attributes of the connection can be changed by the process; others cannot. Which can and which cannot, and how is it done? These are the questions we will answer.

Let us begin by examining all of the data structures related to open les. Each process has a table that is usually called the open file table. ( In 4.4BSD, this table was called the descriptor table, and each entry was called a filedesc structure.) In Linux, this table is the fd array, which is part of a larger structure called the files_struct. The file descriptor returned by the open() system call is actually an index into the open file table of the process making the call. Recall that every process is given three file descriptors when it is created: 0, 1, and 2, respectively, for standard input, output, and error. These are the first three indices in this table, as shown in Figure 4.1.

When a process issues the open() system call, the kernel creates a new file structure and fills the lowest-numbered available slot in the process’s open file table with a pointer to that le structure. The file structures for all open files are contained in a table called the file structure table. which resides in the address space of the kernel. See Figure 4.2.

Attribution

Stewart Weiss (2019), UNIX Application and System Programming, URL: http://www.compsci.hunter.cuny.edu/~sweiss/course_materials/unix_lecture_notes.php

This work is licensed under Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) :  (https://creativecommons.org/licenses/by-sa/4.0/).

VP Flipbook Maker

Transform your content into captivating flipbooks with the user-friendly Visual Paradigm Online Flipbook Maker! Customize them using the intuitive design tools. Try it now!