Implementation and analysis of Unix code example 1

Posted by sONOCOOLO on Tue, 08 Feb 2022 09:57:42 +0100

#####1, Brief implementation of ls(1) command.

int main(int argc,char *argv[])
  DIR *dp;
  struct dirent *dirp;
    err_quit("usage:ls directory_name");

    err_sys("can't open %s",argv[1]);

  1. The function of the above code example is to list all files in a directory;
  2. The following are the problems that may occur when compiling and running;
    I edited the vscode under ubuntu and compiled it with gcc before running it. Of course, you can also download the extension suitable for c/c + + in the application store of vscode, and then Run code. When you encounter the problem that vscode cannot be input, you can check the Run In Teiminal item in the Code Runner extension ✔.
  3. The following is the operation process and results;
    We all know that there are four steps in the compilation process, but we can simplify it to one step:
    gcc xxx.c(xxx.cpp) -o xxx where XXX c/xxx. CPP is C or cpp file - o is the executable file that outputs the previous C or cpp file to the specified name. The executable file here is XXX. Action when executing file:/ XXX / (the last / represents the directory of all the files I want to list. Here is the root directory /)
liufangzhou@liufangzhou-virtual-machine:~/desktop/test$ ls
1      homework1    ls1           ls Simple implementation of.cpp  test
 Assignment 1  homework1.c  ls Simple implementation of  myls              test.cpp
liufangzhou@liufangzhou-virtual-machine:~/desktop/test$ gcc ls Simple implementation of.cpp -o ls1
liufangzhou@liufangzhou-virtual-machine:~/desktop/test$ ./ls1 /
media	usr	sys	run	lib32	var	lost+found	boot	proc	..	bin	srv	etc	.	root	home	sbin	swapfile	lib	tmp	libx32	lib64	mnt	opt

The output format is \ n in the book, but it takes too long to display like that. I change it here to \ t.
#####2, Analysis of examples

  1. The first is the header file. If you want to test run the code example in the running book soon after you buy the book, you will find that it can't run because there is no APUE H this header file, because this header file is written by the author himself, then we have to find this header file through some ways.

    ① Via Download 3e. tar. gz
    ② Download through the resource interface on the asynchronous bookstore website

     Decompression: tar -zcvf src.3e.tar.gz
     cd /apue/apue.3e/

Find the include folder and put aupe H is copied to the default includePath of the c/cpp file. Here, the default include path of vscode I use is / usr/include/Then put APUE Error. In lib directory in 3E Copy the C file to includePath and open APUE H file, add #include "error.c" before #endlif

liufangzhou@liufangzhou-virtual-machine:~/desktop/resources/apue.3e/include$ cd /usr/include
liufangzhou@liufangzhou-virtual-machine:/usr/include$ gedit apue.h

In this way, you can compile and run instance 1.
2. In APUE Reasons for adding #include "error.c" to h
Because in APUE Only err is declared in H_ Quit () and err_ The sys () function does not implement the function function, and the content of the function is in error c (that is. c file), so you can directly reference APUE H header file, of course, can also be directly referenced in the editor error c documents.
🔺 argc and * argv [] in the main function are only used when command line parameters are required. For example, after the executable file is output through gcc compilation, the executable file is executed. At this time, a directory name to display all files needs to be passed in. This method must be used.
🔺 When we use the integrated development environment, such as Dev-c + + and vs 2019, we can pass in parameters without passing in parameters through the command line. At this time, the main function can have invisible parameters.
🔺 argc is the number of parameters that need to be passed in on the command line (that is, the number of strings you enter on the command line). argv [] is the parameter character array, where the 0th parameter is the name of the program itself (including the path).
🔺 argv [] is an array of pointer characters
argv[0]: full pathname to program
argv[1]: points to the first string after the program name executed on the command line.
argv[2]: points to the second string.

liufangzhou@liufangzhou-virtual-machine:~/desktop/test$ cd /usr/include
liufangzhou@liufangzhou-virtual-machine:/usr/include$ gedit error.c

You can view error through gedit Function implementation in C

error. Description of these two functions in C:

  1. err_ The quit function prints relevant information and terminates the program when a fatal error unrelated to the system call occurs.
  2. err_ The sys function prints the relevant information and terminates the program when a fatal error related to the system call occurs.
    err_quit("usage:ls directory_name");

▲ according to the program code of example 1, example 1 is a simple implementation of ls command. The number of parameters to be passed in is 2. Argc records the number of strings entered on the command line, i.e/ ls1 / (here. / ls1 is the first parameter and / is the second parameter) when argc= 2 is to execute err when the number of parameters passed in from the command line is not 2_ Quit function and print the error message, because we need to execute according to the function implemented by the code/ ls1 this executable file must input these two parameters;

    err_sys("can't open %s",argv[1]);

▲ when calling opendir to return a null pointer, either there is no directory or there is a directory, but you have entered it wrong. So you have to use err at this time_ Sys this function prints the information when the system call fails.


▲ loop call the readdir function to read each directory item and print the directory name of the directory item. When no directory item is readable, return a null pointer to end the while loop.


▲ closedir is to close the directory stream indicated by the parameter dp. 0 is returned for successful closing and 1 is returned for failure closing.
At the end of the program, call the exit function with parameter 0 to terminate the program. Generally speaking, 0 is the normal end and 1 ~ 255 is an error.

typedef struct __dirstream DIR;

▲dirent. Definition of DIR in H.

struct __dirstream
void *__fd; /* `struct hurd_fd' pointer for descriptor.   */
char *__data; /* Directory block.   */
int __entry_data; /* Entry number `__data' corresponds to.   */
char *__ptr; /* Current pointer into the block.   */
int __entry_ptr; /* Entry number `__ptr' corresponds to.   */
size_t __allocation; /* Space allocated for the block.   */
size_t __size; /* Total valid data in the block.   */
__libc_lock_define (, __lock) /* Mutex lock for this structure.   */

▲ structure DIR member item.
The DIR structure is similar to FILE. It is an internal structure. This internal structure is used to save the information about the directory currently being read

DIR *dp;
struct dirent *dirp;

The DIR structure we use only declares the pointer of the structure, so the DIR structure should be the same as the FILE structure. When opening a directory, the kernel will help us allocate the memory of the structure.
So is the dirent structure.

struct dirent
   long d_ino; /* inode number Inode number */
   off_t d_off; /* offset to this dirent Offset in catalog file */
   unsigned short d_reclen; /* length of this d_name Long file name */
   unsigned char d_type; /* the type of d_name file type */
   char d_name [NAME_MAX+1]; /* file name (null-terminated) File name, 255 characters maximum */

As for the direct structure, we should first clarify the concept of directory file: this kind of file contains the names of other files and pointers to the information related to these files. From the definition, it can be seen that direct points not only to the directory, but also to the specific files in the directory. The readdir function also reads the files under the directory.

Topics: Linux Unix