I. UNIX architecture
All operating systems provide services for the programs they run, and typical services include executing new programs, opening files, reading files, allocating storage, and so on. Strictly speaking, the operating system can be defined as a kind of software, it controls the computer hardware resources, provides the program running environment. We also make this software the kernel because it is relatively small and is located at the core of the environment. The interface of the kernel is called a system call. Public function libraries are built on top of which normal applications can invoke system calls or public function libraries. The shell is a special application that provides an interface for the bit to run other applications.
II. Documents and directories
1. File system
The Unxi file system is a hierarchical structure of directories and files, where the beginning of everything is called the root (root) directory, and the name of the directory is a character "/". A directory is a file that contains a catalog item, consisting of a filename and file attributes (file type, file size, file owner, file permissions, and so on). It is important to note that the logical view is different from the way it is actually stored on disk. Most implementations of UNIX file systems do not store properties in catalog items, because when a file has multiple hard links, it is difficult to maintain synchronization between multiple copies of a property.
2. File name and path name
Two file names are created automatically when you create a new directory: "." Point to current directory, "..." Point to the parent directory, at the highest level, pointing to the same. A sequence of one or more filenames separated by a slash makes up the path name, and the path name starting with a slash is the absolute pathname, otherwise known as the relative path name.
#include <stdio.h>#include<stdlib.h>#include<dirent.h>intMainintargcChar*argv[]) {DIR*DP; structDirent *Dirp; if(2!=argc) {printf ("Usage:ls directory_name\n"); return-1; } if(NULL = = (DP = Opendir (argv[1])) {printf ("can ' t open%s\n", argv[1]); return-1; } while(NULL! = (Dirp =Readdir (DP))) {printf ("%s\n", dirp->d_name); } closedir (DP); Exit (0);}
1-1: List all files in a directory
3. Working directory and starting directory
Each process has a working directory, and all relative path names are interpreted starting from the working directory, and the process can change its working directory with the CHDIR function. When logging in, the working directory is set to the starting directory, which is obtained from the login entry of the corresponding user in the password file.
Iii. Input and output
1. File descriptors
A file descriptor is usually a small, non-negative integer that the kernel uses to identify the file that a particular process is accessing. When the kernel opens a first-use file or creates a new file, it returns a file descriptor that can be used when reading and writing files. As a rule, every time a new program is run, all of the shells open 3 file descriptors for them, standard input, standard output, and standard error, and if not handled specifically, these three file descriptors are linked to the terminal.
2. I/O without buffering
The functions open, read, write, Lseek, and close provide unbuffered I/O. These functions use file descriptors.
#include <unistd.h>#include<stdio.h>#include<stdlib.h>#defineBuffsize 4096intMainvoid){ intN; CharBuf[buffsize]; while((n = Read (Stdin_fileno, buf, buffsize)) >0) { if(Write (Stdout_fileno, buf, n)! =N) {printf ("Write error.\n"); return-1; } } if(N >0) {printf ("Read error.\n"); return-1; } exit (0);}
1-2: Copy standard input to standard output
Note: 1. header files <unistd.h> function prototypes containing many UNIX system services, Stdid_fileno/stdout_fileno, and read/write are defined therein. The 2.read function returns the number of bytes it reads to, and when an error occurs, read returns -1;3 input ctrl+d as the file terminator, terminating the program;
3. Standard I/O
Standard I/O functions provide a buffered interface for those without buffering I/O functions. There is no need to worry about choosing the best buffer size using standard I/O functions, rather than defining buffsize as in the previous example. It also simplifies the processing of input rows.
#include <unistd.h>#include<stdio.h>#include<stdlib.h>intMainvoid){ intC; while((c = getc (stdin))! =EOF) { if(PUTC (c, stdout) = =EOF) {printf ("Output error.\n"); return-1; } } if(Ferror (stdin)) {printf ("input error.\n"); } exit (0);}
1-3: Copy standard input to standard output with standard I/O
Iv. Procedures and processes
1. Program, process, and process ID
A program is an executable file that is stored in a directory on disk. The kernel uses the EXEC function to read the program into memory and execute the program. The execution instance of a program is called a process, and each process has a unique numeric identifier, called the process ID (non-negative integer).
#include <unistd.h>#include<stdio.h>#include<stdlib.h>int Main ( void) { printf ("Hello World from process ID%ld\n", (long) Getpid ()); Exit (0);}
1-4: Print Process ID
2. Process Control
Process Control main functions: fork, exec, and waitpid.
#include <stdlib.h>#include<stdio.h>#include<string.h>#include<unistd.h>#include<sys/wait.h>#defineMAXLINE 1024intMainvoid){ CharBuff[maxline]; pid_t pid; intstatus; printf ("%% "); while(NULL! =(fgets (Buff, MAXLINE, stdin))) { if('\ n'= = Buff[strlen (Buff)-1]) {Buff[strlen (buff)-1] =0; } if(0> (PID =Fork ())) {printf ("Fork error\n"); return-1; } Else if(0==pid) {EXECLP (Buff, buff, (Char*)0); printf ("couldn ' t execute:%s\n", Buff); return-1; } if(0> (PID = = Waitpid (PID, &status,0)) {printf ("wait pid error\n"); } printf ("%% "); }}
1-5: Read command from standard input and execute
Note: 1.fgets is a standard I/O function that reads one row at a time. The difference from read is that you manage the buffer, do not return the length of the read, and add "\ n" at the end of the read. Instead, EXECLP requires that the parameter be terminated with NULL, so a replacement is required ; 2.fork is called once, returns two times, returns 0 in the subprocess, the parent process returns the child process PID;3.EXECLP to perform the command read from the standard input, which replaces the program file that the child process originally executed with the new program file; 4. Parent and child process synchronization are implemented through Waipid.
3. Thread and Thread ID
All threads within a process share the same address space, file descriptors, stacks, and process-related properties. Because they can access the consent store, each thread needs to take synchronization measures to avoid inconsistencies when accessing shared data. As with the process ID, the thread also has an ID, but the thread ID only works within the process to which it belongs.
Wu, error handling
When a Unix system function goes wrong, it usually returns a negative value, and the shaping variable errno is usually set to the values with specific information. Two rules should be noted for errno: 1. If there is no error, its value is not clear by the routine, so the value is checked only if the return value of the function indicates an error, and 2. Any function does not set the errno value to 0.
#include <unistd.h> #include <stdlib.h> #include < #include <stdio.h> #include <errno.h> int Main (int argc, char * argv[]) {fprintf (stderr, "eacces:%s\n = ENOENT; Perror (argv[ 0 0 );}
1-6: Examples of strerror and perror
Note: 1. We pass the program name (Argv[0]) as a parameter to main, which is a standard UNIX convention.
VI. User identification
The user ID in the password file login entry is a numeric value that identifies a different user to the system. The root user's ID is 0.
#include <unistd.h>#include<stdlib.h>#include<stdio.h>int Main ( void) { printf ("uid =%d, gid =%d\n", Getuid (), Getgid ()); Exit (0);}
1-7: Print user ID and group ID
Seven, signal
The signal (signal) is used to notify the process that a situation has occurred. The process has the following three processing methods: 1. Ignore the signal; 2. Process by default; 3. provide a function. The function is called when the signal occurs. When sending a signal to a process, we must be the owner or superuser of that process.
#include <stdlib.h>#include<stdio.h>#include<string.h>#include<unistd.h>#include<sys/wait.h>#defineMAXLINE 1024Static voidSig_int (int);intMainvoid){ CharBuff[maxline]; pid_t pid; intstatus; if(Signal (SIGINT, sig_int) = =Sig_err) {printf ("Signal error\n"); return-1; } printf ("%% "); while(NULL! =(fgets (Buff, MAXLINE, stdin))) { if('\ n'= = Buff[strlen (Buff)-1]) {Buff[strlen (buff)-1] =0; } if(0> (PID =Fork ())) {printf ("Fork error\n"); return-1; } Else if(0==pid) {EXECLP (Buff, buff, (Char*)0); printf ("couldn ' t execute:%s\n", Buff); return-1; } if(0> (PID = = Waitpid (PID, &status,0)) {printf ("wait pid error\n"); } printf ("%% "); }}voidSig_int (intSigno) {printf ("Interrupt \n%%");}
1-8: Read command from standard input and execute
Eight, time value
The UNIX system maintains 3 process time values for a process: 1. Clock time: The total amount of time the process is running, the value of which is related to the number of simultaneous processes in the system; 2. User CPU Time: The amount of time spent executing user instructions; 3. System CPU Time: The time elapsed for the process to execute kernel programs. The sum of 2 and 3 is also known as CPU time.
Ix. system calls and library functions
From the perspective of the implementation, there is a fundamental difference between the system call and the library function, but from the user's point of view, the difference is not important. The user can replace the library function, but cannot replace the system call. and system calls usually provide a minimal interface, and library functions often provide more complex functionality.
Apue (1)----UNIX Basics