It seems to be a famous book so I bought it <a target="_blank" href="https://www.amazon.co.jp/gp/product/4797328355/ref=as_li_tl?ie=UTF8&camp=247&creative=1211&creativeASIN=4797328355&linkCode=as2&tag=lespacetranqu-22&linkId=b690c3257ff896f2239f1107e > Ordinary Linux programming The royal road of gcc programming that can be learned from the mechanism of Linux <img src = "// ir-jp.amazon-adsystem.com/e/ir?t=lespacetranqu-22&l=am2&o=9&a=4797328355" "width =" 1 "height =" 1 "border =" 0 "alt =" "style =" border: none! Important; margin: 0px! Important; "/> <a target="_blank" href="https://www.amazon.co.jp/gp/product/B075ST51Y5/ref=as_li_tl?ie=UTF8&camp=247&creative=1211&creativeASIN=B075ST51Y5&linkCode=as2&tag=lespacetranqu-22&linkId=aa0915aa60a5a > Ordinary Linux programming 2nd edition: The royal road of gcc programming that can be learned from the mechanism of Linux <img src = "// ir-jp.amazon-adsystem.com/e/ir?t=lespacetranqu-22&l=am2&o=" 9 & a = B075ST51Y5 "width =" 1 "height =" 1 "border =" 0 "alt =" "style =" border: none! Important; margin: 0px! Important; "/>
Try normal Linux programming Part 1 https://qiita.com/uturned0/items/b9ae846f2aff5865c074 Try normal Linux programming Part 2 https://qiita.com/uturned0/items/56beac990cdd6f1059ed Try normal Linux programming Part 3 https://qiita.com/uturned0/items/675092da8aa89c4b1ff0 Part 4 https://qiita.com/uturned0/items/8f5765cfc0f0be8a1981 Part 5 https://qiita.com/uturned0/items/ab97deb489c994a836da Part 6 https://qiita.com/uturned0/items/b7df48e87ae9170f3698
chapter 6
The system call is very slow. It is slow unless it is read in units of 1KB or more. To cover it stdio = standard i / o library, it wasn't a studio!
You can read one line instead of byte unit
Get bytes from fd at once with read () → stdio buffers → program gives 1 byte, return only that Cash-like kanji department
Writing is the same. To some extent, stdio buffers, and when it is collected, it is written by the system call of write ().
If the output destination is a terminal, it will be output in line break units, and if it is unbuffer mode man set vbuf
, it will be output immediately.
stderr is always unbuffer mode. So fast.
The typedef FILE is like the fd ID of stdio. There is a buffer inside, but you don't have to be aware of it.
fd = 0, STDIN_FILENO, stdin fd = 1, STDOUT_FILENO, stdout fd = 2, STDERR_FILENO, stderr
fopen(3)
Oh fopen. You can also see it in higher languages.
NAME
fopen, fdopen, freopen, fmemopen -- stream open functions
LIBRARY
Standard C Library (libc, -lc)
SYNOPSIS
#include <stdio.h>
FILE *
fopen(const char * restrict path, const char * restrict mode);
If you pass a path, it will open () and return a pointer to the FILE type that manages it.
The second argument is about the same as open ()
Close with fclose ()
English books in C language call bytes characters, but there is a big problem in multi-byte languages. Bytes and letters are different. So that's it.
fgetc(3), fputc(3) The return value is int, -1 is returned when EOF
getc(3), putc(3) This is the same as fgetc, but written in macros. It used to be early, but now it makes no difference.
What is a macro? I have forgotten it.
define is one of the instructions to the preprocessor. A briprocessor is a program that processes before compiling. As a pre-processing at compile time, the character string specified by the macro name is replaced with a constant or expression. This replacement is called macro replacement. This process is called macro process. Use define to define macro processing. https://www.sejuku.net/blog/25927
It was define. With c-lang, you can declare not only constants but also functions and variables with define. The values are fixed before compilation, so it's probably useful for environment-dependent variables (64bit, x86, etc.).
ungetc(3) You can return the read bytes to the stream. It's time to look ahead and return to the case where you didn't need it.
If you want to read the number 1234 + -5678, read up to 5 and notice that the next number has begun. Return 5 to the stream and go to the next loop. So that's it
code
#include <stdio.h>
#include <stdlib.h>
int
main(int argc, char *argv[])
{
int i;
for (i=1; i<argc; i++) {
FILE *f;
int c;
f = fopen(argv[i], "r");
if(!f) {
perror(argv[i]);
exit(1);
}
while ((c = fgetc(f)) != EOF) { //Keep fgetc until it hits EOF
// if (putchar(c) < 0) exit(1);
putchar(c);
}
fclose(f);
}
exit(0);
}
Run
$ gcc -Wall -O2 scat.c && ./a.out test
abc
def
xyz
012
AIUEO
Kakikukeko
(c = fgetc (f))
puts the result of fgetc (f) in c. When I tried it, the character code was returned.
When I put abc \ n, it looks like this
97a98b99c10
97 is a and 98 is b. That number is a letter ... where are you writing ()? that?
Ah. Is putchar (c)
a write ()? I'm in a conditional expression, but it's always executed. So that's it.
I remember doing man in such a case.
PUTC(3) BSD Library Functions Manual PUTC(3)
NAME
fputc, putc, putc_unlocked, putchar, putchar_unlocked, putw -- output a character or word to a stream
LIBRARY
Standard C Library (libc, -lc)
SYNOPSIS
#include <stdio.h>
int
fputc(int c, FILE *stream);
I wrote output a character or word to a stream
.
It works without handling the putchar error, but it seems that an error will occur if the other party is a pipe. I tried it, but I couldn't get an error.
fgets(3)
I can read line by line, but there are blood vessels. I can't tell if I read one line normally or if I wrote to the full buffer and stopped. The countermeasure is to make your own with getc (). I only read up to size-1 byte, I write'\ 0'at the end, so I didn't understand it very well.
gets() Never use it. Buffer overflow.
FGETS(3) BSD Library Functions Manual FGETS(3)
NAME
fgets, gets -- get a line from a stream
LIBRARY
Standard C Library (libc, -lc)
SYNOPSIS
#include <stdio.h>
char *
fgets(char * restrict str, int size, FILE * restrict stream);
char *
gets(char *str); <---------
Oh, the title is now BSD library. Hey. gets (char * str)
has no size specified. In other words, it writes endlessly to the * str
that can be a pointer. Even if * str is 8bit, it is recognized only as a memory address, so (probably) the 9th bit will be written as well. It doesn't matter what data is there. Super dangerous.
There are tons of old dangerous functions. You can't use it because it's in the manual.
fputs(const char *buf, FILE *stream);
I don't go and just put it on stream. Not symmetrical to fgets. what is that
#include <error.h>
{
errno = 0;
if (fputs(buf, f) == EOF) {
if (errno != 0) {
//error handling
}
}
}
Is errno returned when all byte strings have been written? Therefore, set errno = 0
in advance and use` if (errno! = 0) to determine if it is a real error.
What is errno?
errno is a globally defined integer value within. Constants corresponding to errors are defined in errno.h, There are system calls and functions that set errno to a value in the event of an error. ... At this time, errno does not change to 0 in any case, so By assigning 0 to errno before processing, You can determine if it is an error in that process. ... Since there is only one errno, it may be rewritten at any time. https://qiita.com/ota42y/items/b2f59d7a82c550648677
Apparently it looks like a c-lang reserved word (defined in error.h?). But I could use perror only with stdio.h.
I thought it was included in stdio.h, but it wasn't.
https://code.woboq.org/userspace/glibc/libio/stdio.h.html
It was imported in perror.
#include <errno.h>
#include <stdio.h>
https://code.woboq.org/userspace/glibc/stdio-common/perror.c.html
But there is no errno
in error.h
https://code.woboq.org/userspace/glibc/misc/error.h.html
I didn't know who was importing how, but I found the source errno.h
# define errno (*__errno_location ())
https://code.woboq.org/gcc/include/errno.h.html
For the time being, it is defined somewhere so you can use it without declaring it. However, if it is not initialized with 0, it cannot be properly identified as an error.
c-lang is really that
int puts(const char +buf);
The output destination is limited to stdout, with \ n at the end. However, if you connect from fgets (), fgets will also be \ n, so line breaks will be duplicated. Really that.
printf() Specify the width by inserting a number between%. 0 padding if you start with% 0. %-Will be left justified.
#include <stdio.h>
#include <stdlib.h>
int
main(int argc, char *argv[])
{
printf("%010x\n", 77) ; // 000000004d
printf("%10s\n", "abc") ; // abc
printf("%-10s\n", "abc") ; // abc
exit(0);
}
result
Printf is convenient, but be careful as it can be dangerous if% is included in the argument. It's dangerous to printf something like fgets () that you don't know what will come.
I don't use scanf () because it's dangerous
6.5 ~~ Long ... I'm heartbroken. Oh, it's work time. end. ~~
I'm drunk, but I start believing that I can remember it later if I write it individually
fread()
size x nmemb read The number of members is nmemb. I thought it was MB-like.
read () write () and system calls are LINUX system calls. Only in the UNIX world. Since fread () is the world of C-lang, it works in other worlds. Hey.
6.6 Currently linux runs on 32bit machine. Hey, how old is this book! !! !!
If you declare it as long, the 32bit and 64bit versions are off_t. What is your name?
Back quotes are annoying because I'm drunk.
6.7
fileno()
int
fileno(FILE *stream);
I'm sleepy, but I did my best to copy and paste ↑. Returns the fd that the stream wraps. Oh, how can I make stream an argument ... I'm sleepy so no
fdopen() Creates a new FILE value that wraps fd and returns a pointer. When and why do you use it ... If you make two, can you move the cursor separately?
file descriptor and FILE are different. Is that different ??? fopen () cannot specify permissino of the newly created file. So open () and fdopen () to create a FILE. Joseki. Common thought. The words of cats that I haven't seen recently
I use fdopen () because I want FILE because ioctl () fcntl () is not in stdin either.
I don't know anymore
fflush() This seems important. Immediately write the contents buffered by stream. It is used when you want to output to the terminal without line breaks such as print. Is it really called flush to output? Writing flush. Something strange. I feel like I'll see it when I strace an error that can't be written to disk. Write when flushed. So that's it.
feof()
I feel like I see this well! !! I wrote that I would definitely use it if I thought. It seems to check if the stream was EOF in the last read. It seems that I wrote it to tell you not to use it. But I feel like I see it often! !!
It seems that the judgment of EOF is quite difficult when I think about it. First of all, even if there is no file (FD), this one will be false, so while (! Feof ()) will loop infinitely, so you have to take care of it before that. Furthermore, this person's comment is amazing
EOF Now we get to EOF. EOF is the response you get from an attempted I/O operation. It means that you were trying to read or write something, but when doing so you failed to read or write any data, and instead the end of the input or output was encountered. This is true for essentially all the I/O APIs, whether it be the C standard library, C++ iostreams, or other libraries. As long as the I/O operations succeed, you simply cannot know whether further, future operations will succeed. You must always first try the operation and then respond to success or failure. https://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong?rq=1%EF%BC%89
Well, the important thing is, in the last line, it's like, "Write it, read it, you'll understand." Maybe you're drunk.
I used to copy and paste fopen () while (feof) in php that I touched at work for the first time, but now I feel that I finally understand the meaning.
clearerr()
When making tail -f, stdio doesn't read () once EOF is picked up. If you clearerr () to make it try hard, it will clear the error flog & EOF flag of stream. So that's it. Then stdio will read () again. Hey.
6.10 strace strace came ---------- =! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! I was waiting for this.
Run this
$ cat hello.c
#include <stdio.h>
int
main(int argc, char *argv[])
{
printf("hello");
return 0;
}
Run
$ gcc heelo.c
$ ./a.out
hello
strace!!!
$ strace ./a.out
execve("./a.out", ["./a.out"], [/* 33 vars */]) = 0
brk(NULL) = 0x1a44000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fa733d28000
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=138375, ...}) = 0
mmap(NULL, 138375, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fa733d06000
close(3) = 0
open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\20&\2\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=2156160, ...}) = 0
mmap(NULL, 3985888, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fa73373a000
mprotect(0x7fa7338fd000, 2097152, PROT_NONE) = 0
mmap(0x7fa733afd000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1c3000) = 0x7fa733afd000
mmap(0x7fa733b03000, 16864, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7fa733b03000
close(3) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fa733d05000
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fa733d03000
arch_prctl(ARCH_SET_FS, 0x7fa733d03740) = 0
mprotect(0x7fa733afd000, 16384, PROT_READ) = 0
mprotect(0x600000, 4096, PROT_READ) = 0
mprotect(0x7fa733d29000, 4096, PROT_READ) = 0
munmap(0x7fa733d06000, 138375) = 0
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 2), ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fa733d27000
write(1, "hello", 5hello) = 5
exit_group(0) = ?
+++ exited with 0 +++
Oh ... I understand somehow ... I understand ...! Thanks to this book ...!
At the beginning, I read libraries such as libc.so.6
.
I'm sure mmap is a memory allocation.
write(1, "hello", 5hello) = 5
This is it. I know I know the first one is stdout. 0 is stdin and 2 is stderr. I don't know what 5 is. 5 hello I don't know what it is, but I can understand it somehow. Oh, 5 may be 5 bytes (5 characters in hello)! !! !!
code
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
static void do_cat(const char *path);
static void die(const char *s);
int
main(int argc, char *arvg[])
{
int i;
if (argc < 2) {
do_cat("/dev/stdin");
}
for (i=1; i<argc; i++) {
do_cat(arvg[i]);
}
exit(0);
}
#define BUFFER_SIZE 4
static void
do_cat(const char *path)
{
int fd;
unsigned char buf[BUFFER_SIZE];
int n;
fd = open(path, O_RDONLY);
if (fd < 0) die(path);
for (;;) {
n = read(fd, buf, sizeof buf);
if (n < 0) die(path);
if (n == 0) break;
if (write(STDOUT_FILENO, buf, n) < 0) die (path);
}
if (close(fd) < 0) die(path);
}
static void
die(const char *s)
{
perror(s);
exit(1);
}
Call a short file
$ ./a.out txt
abc
xyz
try strace
$ strace ./a.out txt
execve("./a.out", ["./a.out", "txt"], [/* 33 vars */]) = 0
brk(NULL) = 0x1505000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fc02f188000
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=138375, ...}) = 0
mmap(NULL, 138375, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fc02f166000
close(3) = 0
open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\20&\2\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=2156160, ...}) = 0
mmap(NULL, 3985888, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fc02eb9a000
mprotect(0x7fc02ed5d000, 2097152, PROT_NONE) = 0
mmap(0x7fc02ef5d000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1c3000) = 0x7fc02ef5d000
mmap(0x7fc02ef63000, 16864, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7fc02ef63000
close(3) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fc02f165000
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fc02f163000
arch_prctl(ARCH_SET_FS, 0x7fc02f163740) = 0
mprotect(0x7fc02ef5d000, 16384, PROT_READ) = 0
mprotect(0x600000, 4096, PROT_READ) = 0
mprotect(0x7fc02f189000, 4096, PROT_READ) = 0
munmap(0x7fc02f166000, 138375) = 0
open("txt", O_RDONLY) = 3
read(3, "abc\n", 4) = 4
write(1, "abc\n", 4abc
) = 4
read(3, "xyz\n", 4) = 4
write(1, "xyz\n", 4xyz
) = 4
read(3, "\n", 4) = 1
write(1, "\n", 1
) = 1
read(3, "", 4) = 0
close(3) = 0
exit_group(0) = ?
+++ exited with 0 +++
2020-11-06-00:56:52 irteamsu@kuji-localdev-001-pool-jp2v-dev:/kc/hello$
The beginning is the same. Is it different that read () appears in the second half? Same yan
strace -e trace=open,read,write,close
It's certainly easy to see when you try
$ strace -e trace=open,read,write,close ./a.out txt
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
close(3) = 0
open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\20&\2\0\0\0\0\0"..., 832) = 832
close(3) = 0
open("txt", O_RDONLY) = 3
read(3, "abc\n", 4) = 4
write(1, "abc\n", 4abc
) = 4
read(3, "xyz\n", 4) = 4
write(1, "xyz\n", 4xyz
) = 4
read(3, "\n", 4) = 1
write(1, "\n", 1
) = 1
read(3, "", 4) = 0
close(3) = 0
+++ exited with 0 +++
code
#include <stdio.h>
#include <stdlib.h>
int
main(int argc, char *argv[])
{
int i;
for (i=1; i<argc; i++) {
FILE *f;
int c;
f = fopen(argv[i], "r");
if(!f) {
perror(argv[i]);
exit(1);
}
while ((c = fgetc(f)) != EOF) { //Keep fgetc until it hits EOF
// if (putchar(c) < 0) exit(1);
putchar(c);
}
fclose(f);
}
exit(0);
}
strace
$ strace -e trace=open,read,write,close ./a.out txt
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
close(3) = 0
open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\20&\2\0\0\0\0\0"..., 832) = 832
close(3) = 0
open("txt", O_RDONLY) = 3
read(3, "abc\nxyz\n\n", 4096) = 9
write(1, "abc\n", 4abc
) = 4
write(1, "xyz\n", 4xyz
) = 4
write(1, "\n", 1
) = 1
read(3, "", 4096) = 0
close(3) = 0
+++ exited with 0 +++
the same? If you think, this is different! !!
read(3, "abc\nxyz\n\n", 4096) = 9
I read ** 4096 bytes ** with this read, and then there is no read! !!
Since I set it to 4 bytes earlier, there were two reads, but stdin is only once. I keep the rest until I say write. So that's it! !! !!
~~ Drunk sinking. take a rest. ~~
Good morning.
did it. It seems that it is not good to write in ascii code because it does not handle the error of putchar. But I felt like I didn't understand anything other than putchar
Source that I don't want you to refer to because it is appropriate ↓. The answer is https://github.com/aamine/stdlinux2-source/blob/master/cat4.c
#include <stdio.h>
#include <stdlib.h>
int
main(int argc, char *argv[])
{
int i;
for (i=1; i<argc; i++) {
FILE *f;
int c;
f = fopen(argv[i], "r");
if(!f) {
perror(argv[i]);
exit(1);
}
while ((c = fgetc(f)) != EOF) { //Keep fgetc until it hits EOF
if (c == 9) { //When tab comes
putchar(92); // \Put out(Number can be taken from ascii table)
putchar(116); //Issue t(Number can be taken from ascii table)
continue;
}
if (c == 10) putchar(36); // \When n comes$Put out(Number can be taken from ascii table)
if (putchar(c) < 0) exit(1);
}
fclose(f);
}
exit(0);
}
check the answer.
Even though it is int c
, it is not a C language that can if (c =='\ n')
. It's an integer. It's sly.
I wanted to use fputs. But if you put int c, you get angry. Is'\ t'in fput and int in putchar? How annoying. I hate you.
It's done, but there seems to be a bug.
My code ↓. The answer is https://github.com/aamine/stdlinux2-source/blob/master/wc-l-stdio.c
#include <stdio.h>
#include <stdlib.h>
int
main(int argc, char *argv[])
{
FILE *f;
int c;
int num = 0;
f = fopen("/dev/stdin", "r");
if(!f) {
perror(argv[0]);
exit(1);
}
while ((c = fgetc(f)) != EOF) { //Keep fgetc until it hits EOF
if (c == 10) num++;
}
printf("%d\n", num++);
fclose(f);
exit(0);
}
result
Correct answer
$ gcc -Wall -O2 wc.c && cat test | ./a.out txt
6
$ wc -l test
6 test
Incorrect answer
$ wc -l /var/log/system.log
6943 /var/log/system.log
$ cat /var/log/system.log | ./a.out
6947
It's a little different. Why are there so many line breaks?
→ It was a misunderstanding. The syslog was just increasing w
$ wc -l /var/log/system.log && cat /var/log/system.log | ./a.out
6984 /var/log/system.log
6984
The answer to the question was here! http://i.loveruby.net/stdlinux2/answers.html
check the answer.
Even though it is int c
, it is not a C language that can if (c =='\ n')
. It's an integer. It's sly.
You can't use large files unless you set it to unsigned long n ;.
If there is a file ending with \ n at the end, it will be counted one more.
I wrote it as standard input, but it also supports file. Unfair. Maybe the problem is different because my book is the first edition.
Yosha ah ah ah ah chapter 6 end! !! !! !! !! !! !! !! !!
You can understand the C code! !! !! !! !! !! !!
You can see where the main function is by looking at the source of the wc command. https://github.com/coreutils/coreutils/blob/master/src/wc.c
I didn't know what was inside
I'm reading this book
<a target="_blank" href="https://www.amazon.co.jp/gp/product/4797328355/ref=as_li_tl?ie=UTF8&camp=247&creative=1211&creativeASIN=4797328355&linkCode=as2&tag=lespacetranqu-22&linkId=b690c3257ff896f2239f1107e > Normal Linux programming The royal road to gcc programming that you can learn from how Linux works <a target="_blank" href="https://www.amazon.co.jp/gp/product/B075ST51Y5/ref=as_li_tl?ie=UTF8&camp=247&creative=1211&creativeASIN=B075ST51Y5&linkCode=as2&tag=lespacetranqu-22&linkId=aa0915aa60a5a > Ordinary Linux programming 2nd edition: The royal road of gcc programming that can be learned from the mechanism of Linux
Recommended Posts