Essayez la programmation Linux normale, partie 6

Cela semble être un livre célèbre alors je l'ai acheté <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=lespacetranb7397102f2397f2397f3b3b > Programmation Linux ordinaire La voie royale de la programmation gcc qui peut être apprise du mécanisme de 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=aaa55pacetran15 > Programmation Linux ordinaire 2ème édition: La voie royale de la programmation gcc qui peut être apprise du mécanisme de 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; "/>

Essayez la programmation Linux normale Partie 1 https://qiita.com/uturned0/items/b9ae846f2aff5865c074 Essayez la programmation Linux normale, partie 2 https://qiita.com/uturned0/items/56beac990cdd6f1059ed Essayez la programmation Linux normale, partie 3 https://qiita.com/uturned0/items/675092da8aa89c4b1ff0 Partie 4 https://qiita.com/uturned0/items/8f5765cfc0f0be8a1981 Partie 5 https://qiita.com/uturned0/items/ab97deb489c994a836da Partie 6 https://qiita.com/uturned0/items/b7df48e87ae9170f3698


chapter 6

l'appel système est très lent. Il est lent, sauf si vous le lisez en unités de 1 Ko ou plus. Pour le couvrir stdio = bibliothèque d'E / S standard, ce n'était pas un studio!

Vous pouvez lire une ligne au lieu d'une unité d'octet

Obtenir des octets collectivement de fd avec read () → tampons stdio → le programme donne 1 octet, ne renvoie que cela Département de kanji en espèces

L'écriture est la même. Tampons Stdio dans une certaine mesure, et quand il est collecté, il est écrit par l'appel système de write ()

Si la destination de sortie est un terminal, elle sera sortie en unités de sauts de ligne, et si c'est le mode sans tampon man set vbuf, elle sera sortie immédiatement. stderr est toujours en mode sans tampon, si rapide.

typedef FILE est comme l'ID fd de stdio. Il y a un tampon à l'intérieur, mais vous ne devez pas en être conscient.

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

fopen(3)

Oh fopen. Vous pouvez également le voir dans des langues supérieures.


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

Si vous passez un chemin, il ouvrira () et renverra un pointeur vers le type FILE qui le gère.

Le deuxième argument est à peu près le même que open ()

Fermer avec fclose ()

Les livres en anglais en langage C appellent des caractères octets, mais il y a un gros problème dans les langages multi-octets. Les octets et les lettres sont différents. Alors c'est tout.

fgetc(3), fputc(3) Si la valeur de retour est int ou EOF, -1 est renvoyé.

getc(3), putc(3) C'est la même chose que fgetc, mais écrit dans des macros. C'était tôt, mais maintenant cela ne fait aucune différence.

Qu'est-ce qu'une macro? Je l'ai oublié.

define est une des instructions au préprocesseur. Un briprocesseur est un programme qui traite avant la compilation. En tant que prétraitement au moment de la compilation, la chaîne de caractères spécifiée par le nom de la macro est remplacée par une constante ou une expression. Ce remplacement est appelé remplacement de macro. Ce processus est appelé processus macro. Utilisez define pour définir le traitement des macros. https://www.sejuku.net/blog/25927

C'était définir. Avec c-lang, vous pouvez déclarer non seulement des constantes mais également des fonctions et des variables avec define. La valeur étant fixée avant la compilation, elle est probablement utile pour les variables dépendant de l'environnement (64 bits, x86, etc.).

ungetc(3) Vous pouvez renvoyer les octets lus au flux. Il est temps de regarder vers l'avenir et de revenir au cas où vous n'en aviez pas besoin.

Si vous voulez lire le nombre 1234 + -5678, lisez jusqu'à 5 et notez que le nombre suivant a commencé. Revenez 5 au flux et passez à la boucle suivante. Alors c'est tout

Faire un chat avec 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) {  //Gardez fgetc jusqu'à ce que vous frappiez EOF
			// if (putchar(c) < 0) exit(1);
			putchar(c);
		}
		fclose(f);
	}
	exit(0);
}


Courir


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

(c = fgetc (f)) met le résultat de fgetc (f) dans c. Quand je l'ai essayé, le code de caractère était de retour. Quand je mets abc \ n, ça ressemble à ça

97a98b99c10

97 est a et 98 est b. Ce nombre est converti en lettres ... Où écrivez-vous () ceci? cette? Ah. Putchar (c) est-il une écriture ()? Je suis dans une expression conditionnelle, mais elle est toujours exécutée. Alors c'est tout. Je me souviens avoir fait l'homme dans un tel cas.


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

J'ai écrit «sortie un caractère ou un mot dans un flux».

Cela fonctionne sans gérer l'erreur putchar, mais il semble qu'une erreur se produira si l'autre partie est un tube. J'ai essayé, mais je n'ai pas pu obtenir d'erreur.

fgets(3)

Je peux lire ligne par ligne, mais il y a des vaisseaux sanguins. Je ne peux pas dire si j'ai lu une ligne normalement ou si j'ai écrit dans le tampon complet et arrêté. La contre-mesure est de créer la vôtre avec getc (). Je ne lis que jusqu'à 1 octet et j'écris «\ 0» à la fin, donc je ne l'ai pas très bien compris.

gets() Ne l'utilisez jamais. Débordement de tampon.

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, le titre est maintenant la bibliothèque BSD. Hey. gets (char * str) n'a pas de taille spécifiée. En d'autres termes, il écrit à l'infini dans le * str qui peut être un pointeur. Même si * str vaut 8 bits, il n'est reconnu qu'en tant qu'adresse mémoire, donc (probablement) le 9ème bit sera également écrit. Peu importe les données présentes. Super dangereux. Il y a des tonnes de vieilles fonctions dangereuses. Vous ne pouvez pas l'utiliser car c'est dans le manuel.

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

Je ne vais pas simplement le mettre sur le flux. Pas symétrique aux fgets. Qu'est-ce que c'est

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

Est-ce que errno est retourné lorsque toutes les chaînes d'octets ont été écrites? Par conséquent, définissez errno = 0 à l'avance et utilisez` if (errno! = 0) pour déterminer s'il s'agit d'une erreur réelle.

Qu'est-ce que errno?

errno est une valeur entière définie globalement dans. Les constantes correspondant aux erreurs sont définies dans errno.h, Il existe des appels système et des fonctions qui définissent errno sur une valeur en cas d'erreur. ... À ce stade, errno ne passe en aucun cas à 0, donc En attribuant 0 à errno avant le traitement, Vous pouvez déterminer s'il s'agit d'une erreur dans ce processus. ... Puisqu'il n'y a qu'un seul errno, il peut être réécrit à tout moment. https://qiita.com/ota42y/items/b2f59d7a82c550648677

Apparemment, cela ressemble à un mot réservé c-lang (défini dans error.h?). Mais je ne pourrais utiliser perror qu'avec stdio.h.

Je pensais qu'il était inclus dans stdio.h, mais ce n'était pas le cas.

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

Il a été importé par erreur.

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

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

Mais il n'y a pas de errno dans error.h https://code.woboq.org/userspace/glibc/misc/error.h.html

Je ne savais pas qui importait comment, mais j'ai trouvé la source errno.h

# define errno (*__errno_location ())

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

Pour le moment, il est défini quelque part, vous pouvez donc l'utiliser sans le déclarer. Cependant, s'il n'est pas initialisé avec 0, il ne peut pas être correctement identifié comme une erreur.

c-lang est vraiment ça

int puts(const char +buf);

La destination de sortie est limitée à stdout, avec \ n à la fin. Cependant, si vous vous connectez depuis fgets (), fgets sera également \ n et le saut de ligne sera doublé. Vraiment ça.

printf() Spécifiez la largeur en insérant un nombre entre%. 0 remplissage si vous commencez par% 0. % -Sera justifié à gauche.

#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 est pratique, mais soyez prudent car cela peut être dangereux si% est inclus dans l'argument. Il est dangereux d'imprimer quelque chose comme fgets () dont vous ne savez pas ce qui va arriver.

Je n'utilise pas scanf () car c'est dangereux

6.5 ~~ Long ... J'ai le cœur brisé. Oh, c'est l'heure du travail. fin. ~~

Je suis ivre, mais je commence à croire que je peux m'en souvenir plus tard si je l'écris individuellement

fread()

taille x nmemb lu Le nombre de membres est nmemb. Je pensais que c'était comme MB.

Read () write () et les appels système sont des appels système LINUX. Uniquement dans le monde UNIX. Puisque fread () est le monde de C-lang, il fonctionne dans d'autres mondes. Hey.

6.6 Actuellement, Linux fonctionne sur une machine 32 bits. Hé, quel âge a ce livre! !! !!

Si vous le déclarez long, les versions 32 bits et 64 bits sont off_t. Quel est votre nom?

define _FILE_OFFSET_BITS 64 Il semble que ce sera long si vous le mettez et le construisez. Alors long long c'est bien ... off_t ...

Les citations sont ennuyeuses parce que je suis ivre

6.7

fileno()

     int
     fileno(FILE *stream);

J'ai sommeil, mais j'ai fait de mon mieux pour copier et coller ↑. Renvoie le fd que le flux encapsule. Oh, comment puis-je faire de stream un argument ... J'ai sommeil donc non

fdopen() Crée une nouvelle valeur FILE qui encapsule fd et renvoie un pointeur. Quand et pourquoi l'utilisez-vous ... Si vous en faites deux, pouvez-vous déplacer le curseur séparément?

Le descripteur de fichier et le FICHIER sont différents. Est-ce différent ??? fopen () ne peut pas spécifier le permissino du fichier nouvellement créé. Alors ouvrez () et fdopen () pour créer un FICHIER. Pierre standard. Pensée commune. Les mots de chats que je n'ai pas vus récemment

ioctl () fcntl () n'est pas dans stdin, donc je veux FILE, donc j'utilise fdopen ().

Je ne sais plus

fflush() Cela semble important. Écrivez immédiatement le contenu mis en mémoire tampon par flux. Il est utilisé lorsque vous souhaitez sortir sur le terminal sans sauts de ligne tels que l'impression. Est-ce vraiment appelé flush à la sortie? Écriture à ras, quelque chose d'étrange. J'ai l'impression de le voir lorsque j'obtiens une erreur qui ne peut pas être écrite sur le disque. Écrivez une fois vidé. Alors c'est tout.

feof()

J'ai l'impression de bien voir ça! !! J'ai écrit que je l'utiliserais certainement si je pensais. Il semble vérifier si le flux était EOF lors de la dernière lecture. Il semble que je l'ai écrit pour vous dire de ne pas l'utiliser. Mais j'ai l'impression de le voir souvent! !!

Il semble que le jugement de l'EOF soit assez difficile quand j'y pense. Tout d'abord, même s'il n'y a pas de fichier (FD), celui-ci sera faux, alors que (! Feof ()) bouclera indéfiniment, donc vous devez faire attention avant cela. De plus, le commentaire de cette personne est incroyable

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

Eh bien, ce qui est important, c'est que dans la dernière ligne, c'est comme: «Écrivez-le, lisez-le et vous comprendrez.» Peut-être que vous êtes ivre.

J'avais l'habitude de copier et coller fopen () pendant (feof) dans le php que j'ai touché au travail pour la première fois, mais maintenant je sens que je comprends enfin le sens.

clearerr()

Lors de la création de tail -f, stdio ne lit pas () une fois EOF récupéré. Si vous effacez () pour essayer, cela effacera le flag d'erreur et l'indicateur EOF du flux. Alors c'est tout. Puis stdio lira à nouveau (). Hey.

6.10 strace strace est venu ---------- =! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! J'étais en train d'attendre pour cela.

strace bonjour le monde

Lance ça

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

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

Courir

$ 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 ... je comprends en quelque sorte ... je comprends ...! Merci à ce livre ...!

Au début, j'ai lu une bibliothèque telle que libc.so.6.

Je suis sûr que mmap est une solution qui sécurise la mémoire.

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

Ça y est. je sais Je sais que le premier est stdout. 0 est stdin et 2 est stderr. Je ne sais pas ce que c'est 5. 5 bonjour, je ne sais pas ce que c'est, mais je peux le comprendre d'une manière ou d'une autre. Oh, 5 peut être 5 octets (5 caractères bonjour)! !! !!

Strace votre propre chat

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

Appeler un court fichier


$ ./a.out txt
abc
xyz

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

Le début est le même. Est-ce différent que read () apparaisse dans la seconde moitié? Même

Comment rendre strace plus facile à voir

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

C'est certainement facile à voir quand vous essayez

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

Chat fait maison partie 2, version 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) {  //Gardez fgetc jusqu'à ce que vous frappiez 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 +++

le même? Si vous pensez, c'est différent! !!

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

J'ai lu ** 4096 octets ** avec cette lecture, puis il n'y a pas de lecture! !!

Depuis que je l'ai défini sur 4 octets plus tôt, il y a eu deux lectures, mais il n'y a qu'un seul stdin. Il garde le reste jusqu'à ce qu'il dise écrire. Alors c'est tout! !! !!

6.11 Exercices

~~ Naufrage ivre. repose toi un peu. ~~

Bonjour.

Problème 1 Réglez \ t sur cat lorsque l'onglet arrive et $ LF lorsque LF arrive.

l'a fait. Il semble qu'il ne soit pas bon de l'écrire avec du code ascii car il ne gère pas l'erreur de putchar. Mais j'avais l'impression de ne rien comprendre d'autre que putchar

Source à laquelle je ne veux pas que vous vous référiez car elle est appropriée ↓. La réponse est 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) {  //Gardez fgetc jusqu'à ce que vous frappiez EOF
			if (c == 9) { //Quand l'onglet vient
				putchar(92); // \Éteindre(Les nombres peuvent être tirés de la table ascii)
				putchar(116); //Problème t(Les nombres peuvent être tirés de la table ascii)
				continue;
			}
			if (c == 10) putchar(36); // \Quand n vient$Éteindre(Les nombres peuvent être tirés de la table ascii)
			if (putchar(c) < 0) exit(1);
		}
		fclose(f);
	}
	exit(0);
}

vérifiez la réponse.

Même s'il s'agit de int c, ce n'est pas un langage C qui peut if (c == '\ n'). C'est un entier. C'est sournois. Je voulais utiliser des fputs. Mais si vous mettez int c, vous vous fâcherez. Est-ce que '\ t'in fput et int dans putchar? Comme c'est ennuyeux. Je te deteste.

Problème 2 Un gars qui peut faire des wc -l depuis stdin

C'est fait, mais il semble y avoir un bug.

Mon code ↓. La réponse est 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) {  //Gardez fgetc jusqu'à ce qu'il atteigne EOF
		if (c == 10)	num++;
	}
	printf("%d\n", num++);
	fclose(f);
	exit(0);
}

résultat


Bonne réponse

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

Réponse incorrecte

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

C'est un peu différent. Pourquoi y a-t-il autant de sauts de ligne?

→ C'était un malentendu. Seul le syslog a augmenté w

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

La réponse à la question était ici! http://i.loveruby.net/stdlinux2/answers.html

vérifiez la réponse.

Même s'il s'agit de int c, ce n'est pas un langage C qui peut if (c == '\ n'). C'est un entier. C'est sournois. Vous ne pouvez pas utiliser un fichier volumineux sauf si vous le définissez sur un long n;. S'il y a un fichier qui se termine par \ n à la fin, il sera compté un de plus. Je l'ai écrit comme entrée standard, mais il prend également en charge les fichiers. Injuste. Peut-être que le problème est différent parce que mon livre est la première édition.

Yosha ah ah ah ah le chapitre 6 est terminé! !! !! !! !! !! !! !! !!

Vous pouvez comprendre le code du langage C! !! !! !! !! !! !!

Vous pouvez voir où se trouve la fonction principale en regardant la source de la commande wc. https://github.com/coreutils/coreutils/blob/master/src/wc.c

Je ne savais pas ce qu'il y avait à l'intérieur


Je lis ce livre

<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=lespacetranb7397102f2397f2397f3b3b > Programmation Linux ordinaire La voie royale de la programmation gcc qui peut être apprise du mécanisme de Linux <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=aaa55pacetran15 > Programmation Linux ordinaire 2ème édition: La voie royale de la programmation gcc qui peut être apprise du mécanisme de Linux

Recommended Posts

Essayez la programmation Linux normale, partie 7
Essayez la programmation Linux normale, partie 2
Essayez la programmation Linux normale, partie 3
Essayez la programmation Linux normale, partie 4
Essayez la programmation Linux normale, partie 6
Essayer la programmation Linux normale Partie 1
Lire la programmation Linux normale (partie 1 uniquement)
[Pour mémoire] Linux Partie 2
Manuel standard Linux partie 5
Manuel standard Linux partie 4
Essayez de programmer avec un shell!
Essayez la programmation GUI avec Hy
Mémo 1 du manuel standard Linux, partie 2
Apprentissage par renforcement 5 Essayez de programmer CartPole?
Essayez de traduire un PDF anglais, partie 1
Essayez d'utiliser SQLAlchemy + MySQL (partie 1)
Essayez d'utiliser SQLAlchemy + MySQL (partie 2)
Faire du son en programmant la partie 2
Mémo du manuel standard Linux, partie 6
[Commande de commodité Linux] Essayez d'insérer exa
Essayez d'utiliser Pillow sur iPython (partie 1)
[Pour mémoire] Éditeur Linux Partie 1 vi
Essayez d'installer OpenAM sur Amazon Linux
Essayez d'utiliser Pillow sur iPython (partie 2)
Essayez l'apprentissage en profondeur avec TensorFlow Partie 2
Essayez le mécanisme de verrouillage du noyau Linux
Essayez d'utiliser Pillow sur iPython (partie 3)
[Commande pratique Linux] Essayez d'insérer bat
Essayez de compiler des commandes Linux (pratique de compilation croisée)