Versuchen Sie es mit normaler Linux-Programmierung Teil 6

Es scheint ein berühmtes Buch zu sein, also habe ich es gekauft <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=lespacetr2f2 > Gewöhnliche Linux-Programmierung Die königliche Straße der gcc-Programmierung, die aus dem Mechanismus von Linux gelernt werden kann <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! Wichtig; Rand: 0px! Wichtig; "/> <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&a0aaa > Gewöhnliche Linux-Programmierung 2. Ausgabe: Der königliche Weg der gcc-Programmierung, der aus dem Mechanismus von Linux gelernt werden kann <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! Wichtig; Rand: 0px! Wichtig; "/>

Versuchen Sie es mit normaler Linux-Programmierung Teil 1 https://qiita.com/uturned0/items/b9ae846f2aff5865c074 Versuchen Sie es mit normaler Linux-Programmierung Teil 2 https://qiita.com/uturned0/items/56beac990cdd6f1059ed Versuchen Sie es mit normaler Linux-Programmierung Teil 3 https://qiita.com/uturned0/items/675092da8aa89c4b1ff0 Teil 4 https://qiita.com/uturned0/items/8f5765cfc0f0be8a1981 Teil 5 https://qiita.com/uturned0/items/ab97deb489c994a836da Teil 6 https://qiita.com/uturned0/items/b7df48e87ae9170f3698


chapter 6

Systemaufruf ist sehr langsam. Es ist langsam, es sei denn, Sie lesen es in Einheiten von 1 KB oder mehr. Um es abzudecken stdio = Standard I / O Bibliothek, es war kein Studio!

Sie können eine Zeile anstelle der Byteeinheit lesen

Holen Sie sich Bytes gemeinsam von fd mit read () → stdio-Puffern → Programm gibt 1 Byte, geben Sie nur das zurück Bargeldähnliche Kanji-Abteilung

Schreiben ist das gleiche. Stdio puffert bis zu einem gewissen Grad, und wenn es gesammelt wird, wird es vom Systemaufruf von write () geschrieben

Wenn das Ausgabeziel ein Terminal ist, wird es in Zeilenumbrucheinheiten ausgegeben, und wenn es sich im Entpufferungsmodus "man set vbuf" befindet, wird es sofort ausgegeben. stderr ist immer im Entpufferungsmodus. So schnell.

typedef FILE ist wie die fd ID von stdio. Es gibt einen Puffer im Inneren, aber Sie müssen sich dessen nicht bewusst sein.

fd = 0, STDIN_FILENO, stdin fd = 1, STDOUT_FILENO, stdout fd = 2, STDERR_FILENO, stderr

fopen(3)

Oh offen. Sie können es auch in höheren Sprachen sehen.


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);

Wenn Sie einen Pfad übergeben, wird open () geöffnet und ein Zeiger auf den FILE-Typ zurückgegeben, der ihn verwaltet.

Das zweite Argument ist ungefähr dasselbe wie open ()

Schließen Sie mit fclose ()

Englische Bücher in C-Sprache rufen Bytezeichen auf, aber es gibt ein großes Problem in Mehrbyte-Sprachen. Bytes und Buchstaben sind unterschiedlich. Das war's.

fgetc(3), fputc(3) Wenn der Rückgabewert int oder EOF ist, wird -1 zurückgegeben.

getc(3), putc(3) Dies ist dasselbe wie fgetc, jedoch in Makros geschrieben. Früher war es früh, aber jetzt macht es keinen Unterschied mehr.

Was ist ein Makro? Ich habe es vergessen

define ist eine der Anweisungen an den Präprozessor. Ein Briprozessor ist ein Programm, das vor dem Kompilieren verarbeitet wird. Als Vorverarbeitung zur Kompilierungszeit wird die durch den Makronamen angegebene Zeichenfolge durch eine Konstante oder einen Ausdruck ersetzt. Diese Ersetzung wird als Makroersetzung bezeichnet. Dieser Prozess wird als Makroprozess bezeichnet. Verwenden Sie define, um die Makroverarbeitung zu definieren. https://www.sejuku.net/blog/25927

Es wurde definiert. Mit c-lang können Sie mit define nicht nur Konstanten, sondern auch Funktionen und Variablen deklarieren. Da der Wert vor dem Kompilieren festgelegt wird, ist er wahrscheinlich für umgebungsabhängige Variablen (64 Bit, x86 usw.) nützlich.

ungetc(3) Sie können die gelesenen Bytes an den Stream zurückgeben. Es ist Zeit, nach vorne zu schauen und zu dem Fall zurückzukehren, in dem Sie ihn nicht gebraucht haben.

Wenn Sie die Nummer 1234 + -5678 lesen möchten, lesen Sie bis zu 5 und stellen Sie fest, dass die nächste Nummer begonnen hat. Kehren Sie 5 zum Stream zurück und fahren Sie mit der nächsten Schleife fort. Das war's

Machen Sie Katze mit stdio

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) {  //Behalte fgetc, bis du EOF drückst
			// if (putchar(c) < 0) exit(1);
			putchar(c);
		}
		fclose(f);
	}
	exit(0);
}


Lauf


$ gcc -Wall -O2 scat.c && ./a.out test
abc
def
xyz
012
AIUEO
Kakikukeko

(c = fgetc (f)) setzt das Ergebnis von fgetc (f) in c. Als ich es versuchte, war der Zeichencode zurück. Wenn ich abc \ n setze, sieht es so aus

97a98b99c10

97 ist a und 98 ist b. Diese Zahl wird in Buchstaben umgewandelt ... Wo schreibst du () das? Das? Ah. Ist putchar (c) ein write ()? Ich bin in einem bedingten Ausdruck, aber er wird immer ausgeführt. Das war's. Ich erinnere mich, dass ich in einem solchen Fall einen Mann gemacht habe.


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);

Ich schrieb "Ausgabe eines Zeichens oder Wortes in einen Stream".

Es funktioniert ohne Behandlung des Putchar-Fehlers, aber es scheint, dass ein Fehler auftritt, wenn die andere Partei eine Pipe ist. Ich habe es versucht, aber ich konnte keinen Fehler bekommen.

fgets(3)

Ich kann Zeile für Zeile lesen, aber es gibt Blutgefäße. Ich kann nicht sagen, ob ich eine Zeile normal lese oder ob ich in den vollen Puffer geschrieben und gestoppt habe. Die Gegenmaßnahme besteht darin, mit getc () eine eigene zu erstellen. Ich habe nur bis zu 1 Byte gelesen und am Ende '\ 0'geschrieben, also habe ich es nicht sehr gut verstanden.

gets() Verwenden Sie es niemals. Pufferüberlauf.

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, der Titel ist jetzt BSD-Bibliothek. Hallo. gets (char * str) hat keine Größe angegeben. Mit anderen Worten, es schreibt endlos in das * str, das ein Zeiger sein kann. Selbst wenn * str 8 Bit ist, wird es nur als Speicheradresse erkannt, sodass (wahrscheinlich) auch das 9. Bit geschrieben wird. Es spielt keine Rolle, welche Daten vorhanden sind. Super gefährlich. Es gibt Unmengen alter gefährlicher Funktionen. Sie können es nicht verwenden, da es im Handbuch enthalten ist.

fputs(const char *buf, FILE *stream);

Ich gehe nicht und stelle es einfach in den Stream. Nicht symmetrisch zu Fgets. was ist das

#include <error.h>
{
	errno = 0;
	if (fputs(buf, f) == EOF) {
		if (errno != 0) {
			//Fehlerbehandlung
		}
	}
}

Wird errno zurückgegeben, wenn alle Byte-Strings geschrieben wurden? Setzen Sie daher im Voraus "errno = 0" und verwenden Sie "if" (errno! = 0), um festzustellen, ob es sich um einen echten Fehler handelt.

Was ist errno?

errno ist ein global definierter ganzzahliger Wert. Konstanten, die Fehlern entsprechen, sind in errno.h definiert. Es gibt Systemaufrufe und Funktionen, die errno im Fehlerfall auf einen Wert setzen. ... Zu diesem Zeitpunkt ändert sich errno auf keinen Fall auf 0 Durch Zuweisen von 0 zu errno vor der Verarbeitung, Sie können feststellen, ob es sich dabei um einen Fehler handelt. ... Da es nur einen Fehler gibt, kann dieser jederzeit neu geschrieben werden. https://qiita.com/ota42y/items/b2f59d7a82c550648677

Anscheinend sieht es aus wie ein reserviertes c-lang-Wort (definiert in error.h?). Aber ich konnte perror nur mit stdio.h verwenden.

Ich dachte, es wäre in stdio.h enthalten, aber es war nicht so.

https://code.woboq.org/userspace/glibc/libio/stdio.h.html

Es wurde perror importiert.

#include <errno.h>
#include <stdio.h>

https://code.woboq.org/userspace/glibc/stdio-common/perror.c.html

Aber es gibt kein "errno" in "error.h" https://code.woboq.org/userspace/glibc/misc/error.h.html

Ich wusste nicht, wer wie importiert, aber ich fand die Quelle "errno.h"

# define errno (*__errno_location ())

https://code.woboq.org/gcc/include/errno.h.html

Derzeit ist es irgendwo definiert, sodass Sie es verwenden können, ohne es zu deklarieren. Wenn es jedoch nicht mit 0 initialisiert wird, kann es nicht ordnungsgemäß als Fehler identifiziert werden.

c-lang ist das wirklich

int puts(const char +buf);

Das Ausgabeziel ist auf stdout beschränkt, mit \ n am Ende. Wenn Sie jedoch eine Verbindung von fgets () herstellen, ist fgets ebenfalls \ n und der Zeilenumbruch wird verdoppelt. Wirklich das.

printf() Geben Sie die Breite an, indem Sie eine Zahl zwischen% einfügen. 0 Auffüllen, wenn Sie mit% 0 beginnen. % - Wird gerechtfertigt bleiben.

#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 image.png

Printf ist praktisch, aber seien Sie vorsichtig, da es gefährlich sein kann, wenn% im Argument enthalten ist. Es ist gefährlich, so etwas wie fgets () auszudrucken, dass Sie nicht wissen, was kommen wird.

Ich benutze scanf () nicht, weil es gefährlich ist

6.5 ~~ Lang ... mir ist das Herz gebrochen. Oh, es ist Arbeitszeit. Ende. ~~

Ich bin betrunken, aber ich glaube, dass ich mich später daran erinnern kann, wenn ich es einzeln schreibe

fread()

Größe x nmemb gelesen Die Anzahl der Mitglieder ist nmemb. Ich fand es MB-ähnlich.

Read () write () und Systemaufrufe sind LINUX-Systemaufrufe. Nur in der UNIX-Welt. Da fread () die Welt von C-lang ist, funktioniert es in anderen Welten. Hallo.

6.6 Derzeit läuft Linux auf einem 32-Bit-Computer. Hey, wie alt ist dieses Buch! !! !!

Wenn Sie es so lange deklarieren, sind die 32-Bit- und 64-Bit-Versionen off_t. Wie heißen Sie?

define _FILE_OFFSET_BITS 64 Es scheint, dass es lange dauern wird, wenn Sie es einfügen und erstellen. Dann ist long long in Ordnung ... off_t ...

Back Quotes sind nervig, weil ich betrunken bin.

6.7

fileno()

     int
     fileno(FILE *stream);

Ich bin müde, aber ich habe mein Bestes getan, um ↑ zu kopieren und einzufügen. Gibt den fd zurück, den der Stream umschließt. Oh, wie kann ich Stream zu einem Argument machen ... Ich bin müde, also nein

fdopen() Erstellt einen neuen FILE-Wert, der fd umschließt und einen Zeiger zurückgibt. Wann und warum verwenden Sie es ... Wenn Sie zwei erstellen, können Sie den Cursor separat bewegen?

Dateideskriptor und DATEI sind unterschiedlich. Ist das anders ??? fopen () kann keine Berechtigung für die neu erstellte Datei angeben. Öffnen Sie also () und fdopen (), um eine DATEI zu erstellen. Standardstein. Gemeinsamer Gedanke. Die Worte von Katzen, die ich in letzter Zeit nicht gesehen habe

ioctl () fcntl () ist nicht in stdin, also möchte ich FILE, also benutze ich fdopen ().

Ich weiß es nicht mehr

fflush() Das scheint wichtig zu sein. Schreiben Sie sofort den vom Stream gepufferten Inhalt. Es wird verwendet, wenn Sie ohne Zeilenumbrüche wie Drucken an das Terminal ausgeben möchten. Wird es wirklich Flush to Output genannt? Flush schreiben. Etwas Seltsames. Ich habe das Gefühl, ich werde es sehen, wenn ich einen Fehler behebe, der nicht auf die Festplatte geschrieben werden kann. Schreiben Sie beim Spülen. Das war's.

feof()

Ich fühle mich wie ich das gut sehe! !! Ich schrieb, dass ich es definitiv benutzen würde, wenn ich dachte. Es scheint zu überprüfen, ob der Stream beim letzten Lesen EOF war. Es scheint, dass ich es geschrieben habe, um dir zu sagen, dass du es nicht benutzen sollst. Aber ich habe das Gefühl, dass ich es oft sehe! !!

Es scheint, dass das Urteil von EOF ziemlich schwierig ist, wenn ich darüber nachdenke. Selbst wenn keine Datei (FD) vorhanden ist, ist diese falsch. Während (! Feof ()) eine Endlosschleife durchläuft, müssen Sie sich vorher darum kümmern. Darüber hinaus ist der Kommentar dieser Person erstaunlich

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

Nun, das Wichtigste ist, in der letzten Zeile heißt es: „Schreib es, lies es und du wirst es verstehen.“ Vielleicht bist du betrunken.

Früher habe ich fopen () während (feof) in das PHP kopiert und eingefügt, das ich zum ersten Mal bei der Arbeit berührt habe, aber jetzt habe ich das Gefühl, dass ich endlich die Bedeutung verstehe.

clearerr()

Bei der Erstellung von tail -f liest stdio nicht (), sobald EOF aufgenommen wurde. Wenn Sie clearerr () verwenden, um es zu versuchen, wird das Fehler-Flog & EOF-Flag des Streams gelöscht. Das war's. Dann liest stdio erneut (). Hallo.

6.10 strace strace kam ---------- =! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! Ich habe darauf gewartet.

strace hallo Welt

Führen Sie dies aus

$ cat hello.c
#include <stdio.h>

int
main(int argc, char *argv[])
{
  printf("hello");
  return 0;
}

Lauf

$ 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 ... ich verstehe irgendwie ... ich verstehe ...! Danke an dieses Buch ...!

Zu Beginn las ich eine Bibliothek wie "libc.so.6".

Ich bin sicher, dass mmap eine speichersichernde ist.

write(1, "hello", 5hello)                    = 5

Das ist es. Ich kenne Ich weiß, der erste ist Standard. 0 ist stdin und 2 ist stderr. Ich weiß nicht, was 5 ist. 5 Hallo, ich weiß nicht, was es ist, aber ich kann es irgendwie verstehen. Oh, 5 können 5 Bytes sein (5 Zeichen in Hallo)! !! !!

Strace deine eigene Katze

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);
}

Rufen Sie eine kurze Datei auf


$ ./a.out txt
abc
xyz

Versuchen Sie es mit 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$

Der Anfang ist der gleiche. Ist es anders, dass read () in der zweiten Hälfte erscheint? Gleich

So machen Sie Strace leichter zu sehen

strace -e trace=open,read,write,close

Es ist sicherlich leicht zu sehen, wenn Sie es versuchen

$ 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 +++

Selbstgemachte Katze Teil 2, Standardversion

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) {  //Behalte fgetc, bis du EOF drückst
			// 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 +++

das Gleiche? Wenn Sie denken, ist das anders! !!

read(3, "abc\nxyz\n\n", 4096)           = 9

Ich lese ** 4096 Bytes ** mit diesem Lesen, und dann gibt es kein Lesen! !!

Da ich es früher auf 4 Bytes eingestellt habe, gab es zwei Lesevorgänge, aber es gibt nur einen Standard. Der Rest bleibt erhalten, bis geschrieben steht. Das war's! !! !!

6.11 Übungen

~~ Betrunken sinken. nimm den Rest. ~~

Guten Morgen.

Problem 1 Setzen Sie \ t auf cat, wenn die Registerkarte kommt, und $ LF, wenn LF kommt.

erledigt. Es scheint nicht gut zu sein, es mit ASCII-Code zu schreiben, da es den Fehler von Putchar nicht behandelt. Aber ich hatte das Gefühl, nichts anderes als Putsch zu verstehen

Quelle, auf die Sie sich nicht beziehen sollen, weil sie angemessen ist ↓. Die Antwort lautet 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) {  //Behalte fgetc, bis du EOF drückst
			if (c == 9) { //Wenn Tab kommt
				putchar(92); // \Herausgeben(Zahlen können der ASCII-Tabelle entnommen werden)
				putchar(116); //Ausgabe t(Zahlen können der ASCII-Tabelle entnommen werden)
				continue;
			}
			if (c == 10) putchar(36); // \Wenn n kommt$Herausgeben(Zahlen können der ASCII-Tabelle entnommen werden)
			if (putchar(c) < 0) exit(1);
		}
		fclose(f);
	}
	exit(0);
}

Überprüfen Sie die Antwort.

Obwohl es "int c" ist, ist es keine C-Sprache, die "if (c ==" \ n ")" kann. Es ist eine ganze Zahl. Es ist schlau. Ich wollte fputs verwenden. Aber wenn Sie int c setzen, werden Sie wütend. Ist '\ t'in fput und int in putchar? Wie nervig. Ich hasse dich.

Problem 2 Ein Typ, der wc -l von stdin aus machen kann

Es ist geschafft, aber es scheint einen Fehler zu geben.

Mein Code ↓. Die Antwort lautet 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) {  //Behalte fgetc, bis du EOF drückst
		if (c == 10)	num++;
	}
	printf("%d\n", num++);
	fclose(f);
	exit(0);
}

Ergebnis


Richtige Antwort

$ gcc -Wall -O2 wc.c && cat test | ./a.out txt
6
$ wc -l test
       6 test  

Falsche Antwort

$ wc -l /var/log/system.log
    6943 /var/log/system.log
$ cat /var/log/system.log | ./a.out
6947

Es ist ein bisschen anders. Warum gibt es so viele Zeilenumbrüche?

→ Es war ein Missverständnis. Nur das Syslog erhöhte sich w

$ wc -l /var/log/system.log && cat /var/log/system.log | ./a.out
    6984 /var/log/system.log
6984

Die Antwort auf die Frage war hier! http://i.loveruby.net/stdlinux2/answers.html

Überprüfen Sie die Antwort.

Obwohl es "int c" ist, ist es keine C-Sprache, die "if (c ==" \ n ")" kann. Es ist eine ganze Zahl. Es ist schlau. Sie können eine große Datei nur verwenden, wenn Sie sie auf unsigned long n; gesetzt haben. Wenn es eine Datei gibt, die am Ende mit \ n endet, wird sie noch einmal gezählt. Ich habe es als Standardeingabe geschrieben, aber es unterstützt auch Datei. Unfair. Vielleicht ist das Problem anders, weil mein Buch die erste Ausgabe ist.

Yosha ah ah ah ah Kapitel 6 ist vorbei! !! !! !! !! !! !! !! !!

Sie können den C-Sprachcode verstehen! !! !! !! !! !! !!

Sie können sehen, wo sich die Hauptfunktion befindet, indem Sie sich die Quelle des Befehls wc ansehen. https://github.com/coreutils/coreutils/blob/master/src/wc.c

Ich wusste nicht, was drin war


Ich lese dieses Buch

<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=lespacetr2f2 > Gewöhnliche Linux-Programmierung Der Königsweg der gcc-Programmierung, der aus dem Mechanismus von Linux gelernt werden kann <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&a0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa > Gewöhnliche Linux-Programmierung 2. Ausgabe: Der königliche Weg der gcc-Programmierung, der aus dem Mechanismus von Linux gelernt werden kann

Recommended Posts

Versuchen Sie es mit normaler Linux-Programmierung Teil 7
Versuchen Sie es mit normaler Linux-Programmierung Teil 2
Versuchen Sie es mit normaler Linux-Programmierung Teil 3
Versuchen Sie es mit normaler Linux-Programmierung Teil 4
Versuchen Sie es mit normaler Linux-Programmierung Teil 6
Versuch einer normalen Linux-Programmierung Teil 1
Lesen Sie die normale Linux-Programmierung (nur Teil 1).
[Für Memo] Linux Teil 2
Linux Standard Lehrbuch Teil 5
Linux Standard Lehrbuch Teil 4
Versuchen Sie, mit einer Shell zu programmieren!
Versuchen Sie die GUI-Programmierung mit Hy
Linux Standard Lehrbuch Memo 1 Teil 2
Verstärkungslernen 5 Versuchen Sie, CartPole zu programmieren?
Versuchen Sie, Englisch PDF Teil 1 zu übersetzen
Versuchen Sie es mit SQLAlchemy + MySQL (Teil 1)
Versuchen Sie es mit SQLAlchemy + MySQL (Teil 2)
Ton erzeugen durch Programmieren von Teil 2
Linux Standard Lehrbuch Memo Teil 6
[Linux Convenience-Befehl] Versuchen Sie, exa einzufügen
Versuchen Sie es mit Pillow auf iPython (Teil 1)
[Für Memo] Linux Part 1 vi Editor
Versuchen Sie, OpenAM unter Amazon Linux zu installieren
Versuchen Sie es mit Pillow auf iPython (Teil 2)
Versuchen Sie es mit TensorFlow Part 2
Probieren Sie den Linux-Kernel-Sperrmechanismus aus
Versuchen Sie es mit Pillow auf iPython (Teil 3).
[Bequemer Linux-Befehl] Versuchen Sie, bat einzufügen
Versuchen Sie, Linux-Befehle zu kompilieren (Cross-Compilation-Praxis)