Unix system IO
file
In Linux, everything is a file. Every file has a type (type) to indicate its role in the system:
- Normal files
(regular file)
contain arbitrary data - Index of
(direction)相
a group of files - The type of socket
(socket)
communication with a process on another machine - …
This blog mainly introduces ordinary files:
- Text files:
text file containing onlyASCII
orUnicode
general character of the document, the text is a series of lines, each with a newline character\n
at the end, which is a digital value0xa
, and theASCII
code ofline feed
the characters(LF)
the same. InWindows
and网络协议
among which are\r\n
(0xd 0xa) to the end. - Binary files
Binary files are ordinary files other than text files, such as our programs, pictures, videos, etc.
open a file
When we want to read or write a file, we first need to tell the system kernel that we want to access this file. The kernel ( open函数
) will return a small non-negative integer ( 描述符
), and we will use this descriptor in our subsequent operations.
At the beginning of the program, three files have been opened by default:
- 0: standard input(stdin)
- 1: standard output(stdout)
- 2: standar error(stderr)
#include<sys/types.h>
#incldue<sys/stat.h>
#include<fcntl.h>
int open(char *filename,int flags,mode_t mode);
- 1
- 2
- 3
- 4
- 5
Parameter introduction:
- filename
The name of the target file to be opened or created - When flags
opens the file, you can pass in multiple parameter options, and use one or more of the following constants to perform或
operations to formfalgs
. - O_RDONLY: Read only open
- O_WRONLY: Write only open
- O_RDWR: The above three constants can be read and written
, one must be specified and only one can be specified - O_CREAT: If the file does not exist, create it, you need to use the mode option. To specify the access rights of the new file
- O_APPEND: Append write, if the file already has content, the data written when opening the file this time is appended to the end of the file without overwriting the original content
- O_TRUNC: If the file exists, truncate it (delete the existing content and rewrite)
- The mode
mode parameter describes the access rights of the new file - S_IRUSR: The user (owner) can read this file
- S_IWUSR: The user (owner) can write this file
- S_IXUSR: The user (owner) can execute this file
- S_IRGRP: Members of the owner's group can read this file
- S_IWGRP: Members of the owner's group can write this file
- S_IXGRP: Members of the owner's group can execute this file
- S_IROTH: Other people (anyone) can read this file
- S_IWOTH: Other people (anyone) can write this file
- S_IXOTH: Other people (anyone) can execute this file
Close file
#include <unistd.h>
int close(int fd);
- 1
- 2
- 3
- fd: The descriptor of the file to be closed.
- Return value: return 0 if successful
- Return -1 on error
Note: When a process terminates, the kernel will automatically close all open files
Read file
#include <unistd.h>
ssize_t read (int fd, void *buf, size_t n);
- 1
- 2
- 3
parameter:
- fd : The descriptor of the file to be read.
- buf : the buffer into which the read data should be put.
- count : The number of bytes to be read.
return value:
- Return the number of bytes read if successful, or 0 if the end of the file has been reached
- If an error occurs, it returns -1 and sets the value of the variable errno.
Note: size_t here is an unsigned integer, and ssize_t is a signed integer.
Write file
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t n);
- 1
- 2
- 3
parameter:
- fd : file descriptor;
- buf : The designated buffer, that is, a pointer, points to a memory unit;
- n : the number of bytes specified in the file to be written;
return value:
- The number of bytes written to the document (success); -1 (error)
write
The function writes buf
the n
number of bytes 描述符
in the file pointed to by fd, returns the number of bytes written when it succeeds, and returns -1 when it fails.
example
#include "csapp.h"
int main(void)
{
char c;
int fd = open(“abc.txt”,O_WRONLY|O_CREAT|O_TRUNC);
while(read(STDIN_FILENO, &c, 1) != 0)
write(fd, &c, 1);
close(fd);
exit(0);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
This is a relatively simple example of storing the content entered into the terminal in a file abc.txt
.
The following is the result of the operation:
hpj@黄培纪:/mnt/d/code/C/Computer Systems/chap10_code$ ./test
test text
^C
- 1
- 2
- 3
abc.txt
The contents are:
test text
Note: There is also a newline character (\n) above which is not displayed
- 1
- 2
- 3
Redirect
In the kernel, there are three related data structures used to represent the opened file:
- Descriptor table
Each process has its own descriptor table (Descriptor table), the table items are indexed by the file descriptor - File table is
a collection of opened files. All processes share this table. The entry includes the location of the file and the reference count (the number of descriptors currently pointing to the entry). Until this number becomes 0, the system kernel will delete it, otherwise it will not. v-node
Table
All processes share this table, and each table entry contains most of the information of the stat structure.
Let's look at a code:
#include "csapp.h"
int main(int argc, char argv[])
{
int fd1, fd2, fd3;
char c1, c2, c3;
char fname = argv[1];
fd1 = Open(fname, O_RDONLY, 0);
fd2 = Open(fname, O_RDONLY, 0);
fd3 = Open(fname, O_RDONLY, 0);
dup2(fd2, fd3);
<span class="token function">Read</span><span class="token punctuation">(</span>fd1<span class="token punctuation">,</span> <span class="token operator">&</span>c1<span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">Read</span><span class="token punctuation">(</span>fd2<span class="token punctuation">,</span> <span class="token operator">&</span>c2<span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">Read</span><span class="token punctuation">(</span>fd3<span class="token punctuation">,</span> <span class="token operator">&</span>c3<span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">printf</span><span class="token punctuation">(</span><span class="token string">"c1 = %c, c2 = %c, c3 = %c\n"</span><span class="token punctuation">,</span> c1<span class="token punctuation">,</span> c2<span class="token punctuation">,</span> c3<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">Close</span><span class="token punctuation">(</span>fd1<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">Close</span><span class="token punctuation">(</span>fd2<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">Close</span><span class="token punctuation">(</span>fd3<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token number">0</span><span class="token punctuation">;</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
Read the following file abcde.txt
:
abcde
- 1
The running results are as follows:
hpj@黄培纪:/mnt/d/code/C/Computer Systems/chap10_code$ ./ffiles1 abcde.txt
c1 = a, c2 = a, c3 = b
- 1
- 2
This is because a dup2
function is used here to change the fd3
file pointed to by the descriptor. This is the redirection process, as shown in the following figure:
Let's look at another example:
#include "csapp.h"
int main(int argc, char argv[])
{
int fd1, fd2, fd3;
char fname = argv[1];
fd1 = Open(fname, O_CREAT|O_TRUNC|O_RDWR, S_IRUSR|S_IWUSR);
Write(fd1, “pqrs”, 4);
fd3 <span class="token operator">=</span> <span class="token function">Open</span><span class="token punctuation">(</span>fname<span class="token punctuation">,</span> O_APPEND<span class="token operator">|</span>O_WRONLY<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">Write</span><span class="token punctuation">(</span>fd3<span class="token punctuation">,</span> <span class="token string">"jklmn"</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
fd2 <span class="token operator">=</span> <span class="token function">dup</span><span class="token punctuation">(</span>fd1<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">/* Allocates new descriptor */</span>
<span class="token function">Write</span><span class="token punctuation">(</span>fd2<span class="token punctuation">,</span> <span class="token string">"wxyz"</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">Write</span><span class="token punctuation">(</span>fd3<span class="token punctuation">,</span> <span class="token string">"ef"</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">Close</span><span class="token punctuation">(</span>fd1<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">Close</span><span class="token punctuation">(</span>fd2<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">Close</span><span class="token punctuation">(</span>fd3<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token number">0</span><span class="token punctuation">;</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
The running results are as follows:
hpj@黄培纪:/mnt/d/code/C/Computer Systems/chap10_code$ ./ffiles3 abc.txt
- 1
abc.txt
The content of the file is entered as follows:
pqrswxyznef
- 1
Into the general process:
First, Write(fd1, "pqrs", 4);
to pqrs
write to abc.txt
in;
then Write(fd3, "jklmn", 5);
the jklmn
write to abc.txt
in;
then under fd1 original point, and Write(fd2, "wxyz", 4);
the wxyz
writing to pqrs
the back, to jklmn
the jklm
cover, into wxyzn
;
and finally Write(fd3, "ef", 2);
in wxyzn
the continued Write ef
.
So abc.txt
the content is pqrswxyznef
.
Finally, let's look at an example:
#include "csapp.h"
int main(int argc, char argv[])
{
int fd1;
int s = getpid() & 0x1;
char c1, c2;
char fname = argv[1];
fd1 = Open(fname, O_RDONLY, 0);
Read(fd1, &c1, 1);
if (fork()) {
int status;
wait(&status);
Read(fd1, &c2, 1);
printf(“Parent: c1 = %c, c2 = %c\n”, c1, c2);
} else {
/* Child */
Read(fd1, &c2, 1);
printf(“Child: c1 = %c, c2 = %c\n”, c1, c2);
}
return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
The read abcde.txt
results are as follows:
hpj@黄培纪:/mnt/d/code/C/Computer Systems/chap10_code$ ./ffiles2 abcde.txt
Child: c1 = a, c2 = b
Parent: c1 = a, c2 = c
- 1
- 2
- 3
The child process also copies the descriptor table of the parent process, but still points to the same file table entry, so the execution Read(fd1, &c2, 1);
result is different.
Reference
- Detailed explanation of file operation functions such as open, creat, write, close, lseek, etc.
- [Reading CSAPP] Land System Input and Output
</div>
<link href="https://csdnimg.cn/release/phoenix/mdeditor/markdown_views-b6c3c6d139.css" rel="stylesheet">
</div>
Unix system IO
file
In Linux, everything is a file. Every file has a type (type) to indicate its role in the system:
- Normal files
(regular file)
contain arbitrary data - Index of
(direction)相
a group of files - The type of socket
(socket)
communication with a process on another machine - …
This blog mainly introduces ordinary files:
- Text files:
text file containing onlyASCII
orUnicode
general character of the document, the text is a series of lines, each with a newline character\n
at the end, which is a digital value0xa
, and theASCII
code ofline feed
the characters(LF)
the same. InWindows
and网络协议
among which are\r\n
(0xd 0xa) to the end. - Binary files
Binary files are ordinary files other than text files, such as our programs, pictures, videos, etc.
open a file
When we want to read or write a file, we first need to tell the system kernel that we want to access this file. The kernel ( open函数
) will return a small non-negative integer ( 描述符
), and we will use this descriptor in our subsequent operations.
At the beginning of the program, three files have been opened by default:
- 0: standard input(stdin)
- 1: standard output(stdout)
- 2: standar error(stderr)
#include<sys/types.h>
#incldue<sys/stat.h>
#include<fcntl.h>