Some small sum to improve the system programming

Some small sum to improve the system programming

Use the buffer to improve efficiency

The reason the use of buffer

In the preparation of the cp command process, using the mechanism of the buffer, the buffer so why should we adopt?

Starting with the role of the cp command buffer seen, first of all realize cp command can call the read (), write () and other core functions to achieve, taking the size of the buffer specified here, every time data is written to the buffer after the new file, you need to call the kernel function to fill the buffer and then further, it is conceivable that if the buffer is too small, need to continue to call the kernel function, cpu must constantly switching kernel mode and user mode, imagine an extreme example, even system call overhead generated over the implementation of the program itself. So we can draw buffer can significantly enhance the efficiency of the cpu.

For input, if there is no data in the buffer, each switch requires a CPU read, wasteful, whereas if the data is present inside the buffer, and the like to be read when the data can be read most disposable. Greatly improved the efficiency of the CPU. But also will lead to a problem it is that when emergency power off, then the cache data may therefore be lost.

For output, if the data is to be printed, the printer is low, the CPU is a high speed. The data is put into a buffer prevents data from being divided into multiple print, this liberation of the CPU, so that it can go to other tasks.

So buffer for improving the processing efficiency of the I / O is critical.

Who raise the efficiency of command

And that brings me to write who command when we used every method to read a data structure, then add a buffer can fill it, read out once more utmp data structure, do the rest just shows these data structures , and then read the kernel function to call to get it?

Think about how to achieve required, to remove a fixed number of disposable utmp data structure maintains an array, then read counter is incremented each time a put, when the counter is equal to the number of the time taken to go get.

 5 #define NRECS 16
 6 #define NULLUT (struct utmp *)NULL
 7 #define UTSIZE (sizeof (struct utmp))
 8 
 9 static char utmpbuf[NRECS * UTSIZE];    
10 static int num_recs;           
11 static int cur_rec;            
12 static int fd_utmp = -1;   


15 struct utmp* utmp_next() {
16     struct utmp* recp;
17     if (fd_utmp == -1) {
18         return NULLUT;
19     }
20     if (cur_rec == num_recs && utmp_reload() == 0) {
21         return NULLUT;
22     }
23     recp = (struct utmp*) &utmpbuf[cur_rec * UTSIZE];
24     cur_rec ++;
25     return recp;
26 }
27 
28 int utmp_reload() {
29     int aimt_read;
30     aimt_read = read(fd_utmp, utmpbuf, NRECS * UTSIZE);
31     num_recs = aimt_read / UTSIZE;
32     cur_rec = 0;
33     return num_recs;
34 }

Here utmp_next as a function of the read buffer is present, it is the previously defined parameters struct utmp *, its return value is struct utmp *, it is a pointer to the structure of the previously defined as parameters, stored on the buffer output structure, a structure pointer directly operate concurrently with the output of a counter is incremented put, and after the function returns, then the counter is reset to 1 cur_rec ,.

Of course utmp_reload function is a buffer mechanism we use a one-time read 16 utmp structure into an array for storage, here to read directly to determine the number of very good utmp by dividing the percentage of bytes, write your own I will be more than an intermediate variable while one more step to take over operations to determine the number of current reading, in fact, is to get rid of this cure on their own thinking, steps need to write clearly in writing before their own, and try to make the code simple .

The main function almost no change:

32 int main() {
33     struct utmp* utbufp;
34     if (utmp_open(UTMP_FILE) == -1) {
35         perror(UTMP_FILE);
36         exit(1);
37     }
38     while ((utbufp = utmp_next()) != (struct utmp*)NULL) {
39         show_info(utbufp);
40     }
41     utmp_close();
42     return 0;
43 }

We can see just need one more step to determine, checking whether the counter reading of the counter is loaded with the same, if the same explanation has been no data is available, while in show_info is to achieve operational function call interface, so no need to rewrite show_info function need to be completed function.

Kernel buffer

Su switching only consuming time and normal users, in order to improve the disk I / O operation efficiency, the kernel also uses buffering technology to improve the access speed. linux system, each process has its own separate buffers, called the process buffer, but the buffer system kernel also has called the kernel buffer. Data blocks on the disk as the kernel will buffer the copy to the kernel buffer disk data blocks, when the user-space process needs to read data from the disk, if the data read just the kernel buffer, the kernel does not directly read the disk, but the kernel buffer to copy the data into the process buffer. When the data is not needed for the kernel buffer, the kernel corresponding data block will be added to the list of requested data, then the process hangs, first-served other processes, and when the execution of the request data, the kernel will Esen block of data from disk after reading the kernel buffer, then copy the data to the process buffer, and finally wake suspended process.

We often read, write, etc., are also doing work exchange kernel buffers and processes buffer, read from the kernel buffer to process buffer, write the opposite, not what we want in the disk and interact directly .

## rewrite operation of the document

Before a lot of work we do is read the data in the file, then use the data (display or other written documents), and said here is not to write data overwrite operation, or I will use this write operation the term, but rather directly to the Linux file information is rewritten, for example, who commands written before, showing the current logged-on user information, so if you want to change the information stored in the user's utmp how to do it?

The first thought is write, but at a slightly thinking you'll know that this is not possible, because even if we write directly overwrite the file that is updated to the next file, not directly overwrite the current file, but this time we should use to another system call lseek.

In UNIX-like systems and UNIX kernel for each open file to save a pointer to the location, all open files has a current file offset (current file offset). cfo is usually a non-negative integer, indicating the number of bytes to the start of the file location of the file currently. Use lseek function can change cfo file.

When we read data from a file, the kernel pointers indicate from where to start, read a specified byte, which is read byte functions include full reasons for reading, then will move the file pointer, point to the next unread word Day, write file operation is similar.

For example, we want to do before the utmp file overwrite operation, we only need to lseek (fd, n * sizeof (struct utmp), SEEK_SET) to view the display after utmp file information, it is necessary to remove the first of several to a few on the line n , and it corresponds to the file pointer is moved backward a few structures, to which to write.

System call error

Kernel through the global variable errno indicates the type of error

errno error code is the last time recording system. Int type code is a value defined in errno.h. Check errno is an important way to debug a program. When an abnormality occurs linux C api function, will generally errno variable (required include errno.h) assigned an integer value, different values ​​represent different meanings.

When an error occurs in system programming, we can guess by looking at the value of errno wrong reasons. Such an error will not puzzled.

#define EPERM        1  /* Operation not permitted */
#define ENOENT       2  /* No such file or directory */
#define ESRCH        3  /* No such process */
#define EINTR        4  /* Interrupted system call */
#define EIO          5   /* I/O error */
#define ENXIO        6  /* No such device or address */
#define E2BIG        7  /* Argument list too long */
#define ENOEXEC      8  /* Exec format error */
#define EBADF        9  /* Bad file number */
#define ECHILD      10  /* No child processes */

This refers to the removal of 10, and all the wrong definition has more than 100, we can do different treatment depending on the error, usually in their own writing code we can use errno, while with perror (), which would allow our code is more standardized.

Published 15 original articles · won praise 13 · views 9059

Guess you like

Origin blog.csdn.net/weixin_43122409/article/details/84535025