#Linux 中 的 GCC 规划 # E / S standard et E / S système

Basé sur C, étudier plus en détail les fonctions du noyau Linux, les fonctions au niveau du système

201708xx

1. Cache

Le cache est de résoudre le problème de la faible vitesse.

1.1 cache IO (IO standard)


  1. Fichier de disque de cache complet .
    Mode d'actualisation: (1) le cache complet est de 8192 octets, et le cache complet est plein, il sera actualisé; (2) fflush (pointeur de flux de fichier FILE *). (3) fclose


  2. Sortie standard du tampon de ligne stdout, entrée standard stdin. stdout—> printf ();
    Mode de rafraîchissement: (1) '\ n', sortie physique du contenu à l'écran; (2) le tampon de ligne est plein, 1024 octets; (3) fflush (stdout).

  3. Pas de
    flux d'erreur standard de cache stderr.
    Mode rafraîchissement: pas de rafraîchissement.
    Sortie directe:
    (1) perror ("XXX"); // Il y aura un succès dans le back
    (2) fprintf (stderr, "XXX \ n");
    (3) exit (0); // # include <stdlib. h> Une fois exécutée, IO sera rafraîchie (sortie directe)
    _Exit (0); // # include <stdlib.h> Une fois exécutée, IO sera rafraîchie (sortie directe)
    _exit (0); // # include <unistd.h> Ne pas actualiser IO (pas de sortie)

  4. Cache operation function
    setbuf (stdin, buffer); // Changer l'emplacement de stockage de l'entrée clavier

#include <stdio.h>
void setbuf( FILE * stream, char* buf);//
void setbuffer(FILE *stream, char *buf, size_t size);
void setlinebuf(FILE *stream);
int setvbuf(FILE *stream, char *buf, int mode, size_t size);//更改流属性

2. E / S standard et E / S système

2,1 E / S standard, Le mécanisme de tampon est utilisé par défaut .

  1. Entrée et sortie standard IO. Le fichier d'en-tête est "stdio.h".
  2. Prenez fopen comme exemple, utilisez la commande man fopen pour afficher les informations.
  3. Ouvrez le texte (mettez-le en mémoire).
    fopen: Ouvrez un fichier,
    créez un tampon (deux tampons seront créés en mode lecture-écriture)
    et créez une structure de données FILE qui contient des données liées au fichier et au tampon.
  4. Texte de l'opération.
    Les fichiers binaires peuvent être manipulés: fread fwrite
    peut manipuler les fichiers de caractères: fgets fputs fgetc fputc fscanf fprintf Pendant
    un processus de lecture, fscanf se termine lorsqu'il rencontre un espace et une nouvelle ligne, et il se termine également lorsque vous faites attention à un espace. C'est différent de fgets, qui ne se termine pas quand il rencontre un espace.
  5. Fermez le texte.
    fclose: ferme le fichier et actualise le cache. Mettez les données de texte dans la mémoire pour le local.
#include <stdio.h>
FILE *	fopen(const char *path, const char *mode);
FILE *	fdopen(int fd, const char *mode);//重新打开系统IO/文本IO返回的fd文件描述符,得到新的文件指针fp。
FILE *	freopen(const char *path, const char *mode, FILE *stream); //重定向//用于更改与标准文本流(stderr、stdin或stdout)关联的文件。
size_t 	fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
size_t	fwrite(const void *ptr, size_t size, size_t nmemb,  FILE *stream);
int	fclose(FILE *stream);

2.2 Système IO, Aussi appelé E / S de fichier, E / S de bas niveau. Pas de cache .

  1. Prenez open comme exemple, vérifiez les informations correspondantes via man 2 open.
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int 	open(const char *pathname, int flags);
int 	open(const char *pathname, int flags, mode_t mode);
int 	creat(const char *pathname, mode_t mode);
int 	openat(int dirfd, const char *pathname, int flags);
int 	openat(int dirfd, const char *pathname, int flags, mode_t mode);
//open(), openat(), and creat() 返回文件描述符fd或者-1(失败)

#include <unistd.h> //unix standard
//这里的ssize 相当于int,这里是用于跨平台,兼容性。
ssize_t 	read(int fd, void *buf, size_t count);//成功返回读取的字节数 //失败返回-1
ssize_t 	write(int fd, const void *buf, size_t count);//失败返回-1
int 		close(int fd);

#include <sys/ioctl.h>
int 	ioctl(int fd, unsigned long request, ...);

#include <unistd.h>
#include <fcntl.h>
int 	fcntl(int fd, int cmd, ... /* arg */ );//可用于追加文件的权限。等等。

#include <sys/types.h>
#include <unistd.h>
off_t 	lseek(int fd, off_t offset, int whence);

3. Quelques codes de test

3.1 Imprimez les lettres de la chaîne une par une, sans emballage.

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
void delay(int time)
{
 	usleep(time*10000);
}
int main(int argc,char* argv[])
{
 	if(argc<2)
 	{
  		printf("缺少\n");
  		return -1;
 	}
/*
 	if(argc!=2)
 	{
  		char* p="参数不够";
  		fprintf(stderr,"%s\n",p);//标准错误流,无缓存,不用刷新
  		//或者  
  		perror("参数不够\n");//标准错误流,无缓存,不用刷新
  		return -1;
 	}
*/
	 int i=0;
 	while(argv[1][i])
 	{
  		printf("%c ",argv[1][i]);
  		fflush(stdout);//fflush刷新行缓存(stdout)
  		delay(10);
  		i++;
	 }
 	printf("\n");
 	return 0;
}

Effet de l'opération: les membres de la chaîne sont imprimés un par un (pas tous en même temps).

kshine@kshine-virtual-machine:~/桌面/lsd/0817$ gcc demo1.c -o D1 -Wall
kshine@kshine-virtual-machine:~/桌面/lsd/0817$ ./D1
缺少
kshine@kshine-virtual-machine:~/桌面/lsd/0817$ ./D1 Kshine2017
K s h i n e 2 0 1 7 

3.2 Fonctionnement du système IO (texte IO)

  1. Ouvrez le fichier spécifié.
  2. Écrivez-y mon numéro porte-bonheur 23. À ce moment, le pointeur de décalage du fichier a reculé.
  3. Avec lseek, déplacez le pointeur de décalage vers l'avant.
  4. Relisez les données qui viennent d'être écrites.
  5. Fermez enfin le fichier.
//标准IO库函数
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//系统io
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
int main(int argc, char** argv)
{
 	if(argc<2)
 	{
  		printf("输入出错\t");
  		fprintf(stderr,"%s\n",strerror(errno));
  		return 0;
 	}
	 int fd = open(argv[1],O_RDWR | O_TRUNC |O_CREAT ,0664);
 	//-------------
 	int value=23;//我的幸运数字23
	 if(write(fd,&value,sizeof(int))==-1)
 	{
  		printf("写 出错\t");
  		fprintf(stderr,"%s\n",strerror(errno));
  		return 0;
 	}
 	printf("write success!\n");
 	//------------
 	int value2=0;
 	//lseek(fd,-2,SEEK_CUR);//方法一:在当前的位置的基础上,向前移动2位。
 	lseek(fd,0,SEEK_SET);//方法二:直接设置偏移指针到文件开头。
 	printf("offset success!\n");
 	if(read(fd,&value2,sizeof(int))==-1)
 	{
  		printf("读错误\t");
  		fprintf(stderr,"%s\n",strerror(errno));
  		return 0;
 	}
 	printf("read success!\n");
 	printf("the value is : %d\n",value2); 
 	close(fd);
 	return 0;
}

résultat de l'opération:

kshine@kshine-virtual-machine:~/桌面/lsd/0817$ gcc demo2.c -o D1 -Wall
kshine@kshine-virtual-machine:~/桌面/lsd/0817$ ./D1 text2
write success!
offset success!
read success!
the value is : 23

3.3 System IO + standard IO, écrivez les informations d'équation d'ip et de port dans le fichier et extrayez les informations numériques.

Il est nécessaire de décomposer 192.168.1.1 via l'E / S système et de le stocker dans le premier tableau de caractères, de le décomposer en 8080 et de le stocker dans le second tableau de caractères. Imprimez enfin.

  • Tout d'abord, écrivez les informations dans le fichier via l'E / S système.
  • Repasserfdopen, Accédez au fonctionnement des E / S standard.
  • À l'aide d'E / S standard, replacez le pointeur de décalage au début du fichier.
  • Lisez les informations du fichier et extrayez-les.
  • Fermer le fichier
//标准库
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
//系统库
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
int main(int argc,char* argv[])
{
 	//程序执行命令,无后接的字符串
 	if(argc>=2)
 	{
  		printf("执行命令错误\n");
  		//fprintf(stderr,"%s\n",strerror(errno));
  		return 0;
 	}
 	//用户输入
 	int i=0;
 	char str1[30]="";
 	char str2[30]="";
 	printf("请输入字符串1\n");//行缓存,\n刷新输出
 	//scanf("%s%s",str1,str2);
 	//gets(str1);//编译告警:gets函数中,没有指定接受的长度,可能会超出存储范围。不建议使用。
 	fgets(str1,30,stdin);
 	printf("请输入字符串2\n");
	 //gets(str2);
 	fgets(str2,30,stdin);
 	//系统IO的操作---------------------------------------
 	//1、打开文件
 	//int open(const char *pathname, int flags, mode_t mode);
 	int fd = open("hw1",O_RDWR | O_CREAT | O_TRUNC,0664); //通过文件符打开 //权限 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH
 	printf("open success!\n");//行缓存 通过\n 刷新输出
 	//2、写入数据  
 	if(write(fd,str1,sizeof(char)*30) == -1 || write(fd,str2,sizeof(char)*30) == -1 )
 	{
  		printf("写出错!\n");
  		fprintf(stderr,"%s\n",strerror(errno));
  		return 0;
 	}
 	printf("write success!\n");
 	//3、偏移文件操作指针的位置
 	//lseek(fd,0,SEEK_SET);
 	FILE* fp =fdopen(fd,"r+");
    	//r+和w+都是读写,但是w+会清空已有文件
 	fseek(fp,0,SEEK_SET);
 	//4、读取数据
	 i=0;
 	char ch=0;
 	int flag=0,count=0;//用于切换存储的数组
 	for(;;)
 	{
  		//读取单个字符
  		if(read(fd,&ch,sizeof(char)) == 0 )
  		{
   			break;
  		}
  		if((ch <= '9'&& ch >= '0')|| ch== '.')//如果是数字或者.
  		{
   			if(ch == '.' && count>=0  )//记录‘.’的个数
   			{
    				count++;
  			 }
  			 if(flag==0)//第一个字符串存储
   			{
    				str1[i]=ch;
    				i++;
    				continue;
   			}
   			if(flag >= 1)//1 第二个字符开始 2
   			{
    				flag=2;
    				str2[i]=ch;
    				i++;
    				continue;
   			}
   			continue;
  		}
  		//已经经过3个. 到这里还不是数字
  		else if(count==3)
  		{
  			 count=-10;//结束计数
   			str1[i]='\0';
   			flag=1;//切换到字符串2
   			i=0;  
  		}
  		if(flag==2)//已经在str2中写了数字了,这里不是数字,则端口的数值结束
  		{
   			str2[i]='\0';
   			break;
  		}
 	}
 	printf("read success!\n");
 	//5、关闭文件
 	close(fd);
 	printf("close success!\n");
 	//6、输出
 	printf("%s\n",str1);
 	printf("%s\n",str2);
 	return 0;
}

résultat de l'opération:

kshine@kshine-virtual-machine:~/桌面/lsd/0817$ gcc homework1.c -o D1 -Wall
kshine@kshine-virtual-machine:~/桌面/lsd/0817$ ./D1
请输入字符串1
IP = 192.168.1.1
请输入字符串2
PORT = 8080
open success!
write success!
read success!
close success!
192.168.1.1
8080

3.4 Système IO, réaliser la fonction de copie

Nécessite que le nom de fichier 1, le nom de fichier 2 soit transmis à partir du paramètre principal.

//标准库
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
//系统库
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
int main(int argc,char* argv[])
{
        //程序执行命令
        if(argc<3)
        {
                printf("执行参数不够\n");
                //fprintf(stderr,"%s\n",strerror(errno));
                return 0;
        }       
        //系统IO的操作---------------------------------------
 	//1、打开文件
 	int fd1 = open(argv[1],O_RDONLY,0664);//文件1,打开 读取 
 	printf("open file1 success!\n");
	int fd2 = open(argv[2],O_WRONLY | O_CREAT | O_TRUNC,0664); //通过文件符打开//权限 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH
	printf("open file2 success!\n");//行缓存 通过\n 刷新输出
 	//2、单字符搬运
 	char ch=0;
 	while(1)
 	{
  		//读取单个字符
		if(read(fd1,&ch,sizeof(char)) == 0 )
                {
                        break;
                }
  		write(fd2,&ch,sizeof(char));
 	}
        printf("copy complete!\n");
	//3、关闭
 	close(fd1);
 	close(fd2);
	return 0;
}

3.5 Redirection

Imprimez la table de multiplication neuf-neuf-neuf dans un fichier, nécessitant une redirection.
Il existe deux façons de rediriger:

  1. libre
  2. dup2
//标准IO库函数
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//系统io
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
int main(int argc ,char** argv)
{
 	if(argc!=2)
 	{
  		fprintf(stderr,"命令参数个数错误\n");
  		return 0;
 	}
 	//创建文件
	 int fd=creat(argv[1],0664);//int creat(const char *pathname, mode_t mode);
 #if 1
 	//重定向
 	if(freopen(argv[1],"w",stdout)==NULL)
 	{
  		printf("重定向失败\n");
  		return 0;
 	} 
 #endif
 #if 0
 	/* 重定向 */  
        if (-1 == dup2(fd,STDOUT_FILENO) )
        {  
                printf("can't redirect fd error\n");  
                exit(1);  
        }  
 #endif
 	//输出
 	int i=1,j=1;
 	printf("九九乘法表:\n");
 	for(i=1;i<=9;i++)
 	{
  		for(j=1;j<=9;j++)
  		{
   			printf("%dx%d=%d\t",i,j,i*j);
  		}
  		printf("\n");
 	}
 	//还原重定向
 #if 1
 	if(freopen("/dev/tty","w",stdout)==NULL)
        {
                printf("重定向失败\n");
                return 0;
        }
 #endif
 #if 0
 	/* 恢复stdout */  
        if (-1 != dup2(fd,STDOUT_FILENO) ) 
        {  
                printf("recover fd ok \n");  
                write(STDOUT_FILENO,"stdout\n",7);   /* 恢复后,写入stdout应该向屏幕输出 */  
        }  
 #endif
 	//再次输出
 	printf("write ok \n");
 	//关闭
 	close(fd);
 	return 0;
}

résultat de l'opération:

kshine@kshine-virtual-machine:~/桌面/lsd/0817$ gcc homework3.c -o D1 -Wall
kshine@kshine-virtual-machine:~/桌面/lsd/0817$ ./D1
命令参数个数错误
kshine@kshine-virtual-machine:~/桌面/lsd/0817$ ./D1 jjcfb
write ok 
kshine@kshine-virtual-machine:~/桌面/lsd/0817$ cat jjcfb 
九九乘法表:
1x1=1 1x2=2 1x3=3 1x4=4 1x5=5 1x6=6 1x7=7 1x8=8 1x9=9 
2x1=2 2x2=4 2x3=6 2x4=8 2x5=10 2x6=12 2x7=14 2x8=16 2x9=18 
3x1=3 3x2=6 3x3=9 3x4=12 3x5=15 3x6=18 3x7=21 3x8=24 3x9=27 
4x1=4 4x2=8 4x3=12 4x4=16 4x5=20 4x6=24 4x7=28 4x8=32 4x9=36 
5x1=5 5x2=10 5x3=15 5x4=20 5x5=25 5x6=30 5x7=35 5x8=40 5x9=45 
6x1=6 6x2=12 6x3=18 6x4=24 6x5=30 6x6=36 6x7=42 6x8=48 6x9=54 
7x1=7 7x2=14 7x3=21 7x4=28 7x5=35 7x6=42 7x7=49 7x8=56 7x9=63 
8x1=8 8x2=16 8x3=24 8x4=32 8x5=40 8x6=48 8x7=56 8x8=64 8x9=72 
9x1=9 9x2=18 9x3=27 9x4=36 9x5=45 9x6=54 9x7=63 9x8=72 9x9=81

3.6 System IO, modifier les permissions des fichiers ouverts

1. Ouvrez un fichier avec des autorisations de lecture et d'écriture. Si le fichier n'existe pas, vous devez toucher un fichier vide.
2. Augmentez la permission "ajouter" via fcntl.
3. Ajoutez helloworld à écrire, et il y a helloworld dans le fichier final.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
int main(int argc, char** argv)
{
 	//打开文件
 	int fd = open ( argv[1],O_RDWR,0664);
 	if(fd==-1)
 	{
  		printf("打开失败\n");   
  		return 0;
   	}
 	//修改权限
 	int get_fl=(fcntl(fd,F_GETFL)) | O_APPEND ;
 	//fcntl(fd,F_SETFL,get_fl|O_APPEND);//这样可能会在跨系统的时候,产生二异性
 	//传参的时候,尽量保证传定值
 	fcntl(fd,F_SETFL,get_fl); 
 	//写入
 	char str[]="helloworld";
 	if(write(fd,str,strlen(str))==-1)
 	{
  		fprintf(stderr,"%s\n",strerror(errno));
  		return 0;
 	}
 	//关闭
 	close(fd);
 	return 0;
}

résultat de l'opération

kshine@kshine-virtual-machine:~/桌面/lsd/0818$ gcc demo2.c -o main -Wall
kshine@kshine-virtual-machine:~/桌面/lsd/0818$ ./main
打开失败
kshine@kshine-virtual-machine:~/桌面/lsd/0818$ ./main Test
打开失败
kshine@kshine-virtual-machine:~/桌面/lsd/0818$ touch Test
kshine@kshine-virtual-machine:~/桌面/lsd/0818$ ./main Test
kshine@kshine-virtual-machine:~/桌面/lsd/0818$ cat Test 
helloworld

3.7 System IO, umask et accès

utilisationfonction umaskModifiez la valeur du masque umask en: les fichiers que vous créez sont actuellement uniquement en écriture.
utilisationfonction ouverteCréez le fichier a.txt pour rendre les autorisations de fichier rw-x-wx.
utilisationaccèsDéterminez si le fichier contient un fichier inscriptible.
S'il existe des fichiers inscriptibles, utilisez chmod pour supprimer les fichiers inscriptibles de l'utilisateur.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
int main(int argc,char* argv[])
{
	//1、umask设置删除的权限信息,都是只写
 		//mode_t umask(mode_t mask);
 	mode_t new_umask;  
 	new_umask=0333;//  
 	umask(new_umask);  
 	printf("已设置权限掩码!\n");  
	//2、使用open 函数创建文件a.txt使文件的权限为rw---x-wx。
 	int fd = open(argv[1],O_CREAT|O_TRUNC|O_RDWR,S_IRUSR|S_IWUSR|S_IXGRP|S_IWOTH|S_IXOTH);
 	close(fd);
 	printf("创建了文件%s,有写的权限\n",argv[1]);
	// system("ls -l");
	//3、使用access判断该文件是否具有可写文件。
 		//int access(const char *pathname, int mode);
	if(access(argv[1],R_OK)==0)
 	{
  		printf("判断,具有写的权限!\n");
 	}
 	else
 	{
  		printf("用户不具有写的权限\n");
 	}
	//4、如果有可写文件,则使用chmod 将用户的可写文件删除。 
 		//int chmod(const char *path, mode_t mode);
 	if(chmod(argv[1],S_IRUSR|S_IXGRP|S_IXOTH)==-1)
 	{
  		fprintf(stderr,"%s\n",strerror(errno));
  		return 0;
 	}
 	printf("已删除可写权限\n"); 
 	system("ls -l");
 	return 0;
}

3.8 Juger le type de fichier par nom de fichier

//int stat(const char *path, struct stat *buf);
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
int main(int argc,char* argv[])
{
        if(argc!=2)
        {
                fprintf(stderr,"%s\n",strerror(errno));
                return 0;
        }
//定义结构体
 	struct stat  buffer={};//已经初始化
 	//memset(&buf,0,sizeof(struct stat));
//传入文件信息
 	// int stat(const char *path, struct stat *buf);
 //  路径的地址  结构体类型的存储变量
 	if(stat(argv[1], &buffer)==-1)
 /*****************************************
 RETURN VALUE
 On success, zero is returned.  
 On error,     -1 is returned,
 and errno is set appropriately.
***************************************/
 	{
  		fprintf(stderr,"%s\n",strerror(errno));
  		return 0;
 	}
//判断文件信息
 	//buffer.st_mode
 /************************************
 The following POSIX macros are defined to check the file type using the st_mode field:
           S_ISREG(m)  is it a regular file?
           S_ISDIR(m)  directory?
           S_ISCHR(m)  character device?
           S_ISBLK(m)  block device?
           S_ISFIFO(m) FIFO (named pipe)?
           S_ISLNK(m)  symbolic link? (Not in POSIX.1-1996.)
           S_ISSOCK(m) socket? (Not in POSIX.1-1996.)
 ************************************/ 
 	if(S_ISREG(buffer.st_mode))
                printf("a regular file\n");
        if(S_ISDIR(buffer.st_mode))
                printf("directory\n");
        if(S_ISCHR(buffer.st_mode))
                printf("character device\n");
        if(S_ISBLK(buffer.st_mode))
                printf("block device\n");
        if(S_ISFIFO(buffer.st_mode))
                printf("FIFO (named pipe)\n");
        if(S_ISLNK(buffer.st_mode))
                printf("symbolic link\n");
        if(S_ISSOCK(buffer.st_mode))
                printf("socket\n");
        return 0;
}

3.9 Afficher tous les noms de fichiers dans le répertoire spécifié et ses sous-répertoires

Utiliser des appels récursifs

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <dirent.h>
//判断是不是目录
int judge_dir(char *name);
//展示目录名或者文件名
void kshine_ls(char* name);
int main(int argc,char* argv[])
{
 	if(argc!=2)
 	{
  		fprintf(stderr,"%s\n",strerror(errno));
  		return 0;
 	}
 	kshine_ls(argv[1]);
 	return 0;
}
void kshine_ls(char* name)
{
 	printf("---- 进入  目录 ----\n");
 	//DIR *opendir(const char *name);  //成功返回目录指针,失败返回NULL,有errno
 	//struct dirent *readdir(DIR *dirp);  //成功返回指针,结尾或者出错返回NULL
 	//void rewinddir(DIR *dirp);  //成功返回0,出错返回-1
 	//int closedir(DIR *dirp);  //成功返回0,出错返回-1
//打开目录(根据目录名,定义一个目录指针)
 	DIR* dir_p = opendir(name);
 	if(dir_p == NULL)
 	{
  		fprintf(stderr,"%s\n",strerror(errno));
  		return;
 	}
//读取目录(根据目录指针dir_p ,返回d_p指针)
 	struct dirent  *d_p;
 	while(1)
 	{
  		d_p = readdir(dir_p);
  		if(d_p == NULL)
  		{
  			 break;
 		 }
 		//显示目录名称 
 		//d_name[256]; /* filename */
  		printf("%s\n",d_p->d_name);
  		if(strcmp(d_p->d_name,".") == 0 || strcmp(d_p->d_name , "..")==0)
 		 {
   			continue; 
  		}
  		if(judge_dir(d_p->d_name) == 1)//如果是目录
 		 {
   			kshine_ls(d_p->d_name); //递归调用,用于显示子目录的文件名
  		}
	 }
//关闭目录
 	closedir(dir_p);
 	printf("-------------------\n\n");
}
int judge_dir(char *name)
{
 //定义结构体
        struct stat     buffer={};//已经初始化
//传入文件信息
        // int stat(const char *path, struct stat *buf);
        //路径的地址    结构体类型的存储变量
        if(stat(name, &buffer)==-1)
        {
               // fprintf(stderr,"%s\n",strerror(errno));
               // return 0;
        }
//判断文件信息
        if(S_ISDIR(buffer.st_mode))
               return 1;// printf("directory\n");
 	else
 	return 0;
}

résultat de l'opération:
3.9 Afficher la structure des répertoires

Une façon d'écrire plus standardisée est la suivante:

//递归打印路径
#include <dirent.h>
#include<stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
void show_name(char* cwd);
int main(int argc,char** argv)
{
 	if(argc != 2)
 	{
  		fprintf(stderr,"参数不够\n");
  		return ;
 	}
 	show_name(argv[1]);
    return 0;
}
void show_name(char* cwd)
{
 	DIR* dir_t = opendir(cwd);
 	if(dir_t == NULL)
 	{
  		return ;
 	}
 	chdir(cwd);
 	struct dirent* dirent_t = NULL;
 	while(1)
 	{
  		if((dirent_t = readdir(dir_t)) == NULL)
  		{
   			break;
  		}
  		if(strcmp(dirent_t -> d_name,".")==0 || strcmp(dirent_t->d_name,"..") == 0)
 		{
   			continue;
  		}
  		if(dirent_t -> d_type == DT_DIR)
  		{
   			printf("目录:%s\n\n\n",dirent_t->d_name);
   			show_name(dirent_t -> d_name);
   			chdir("..");
  		}
  		printf("I——NODE:%ld\t文件名:%s\n",dirent_t->d_ino,dirent_t->d_name);
 	}
}

3.10 La différence entre la fonction stat et la fonction lstat

Lors de l'appel du fichier exécutable, suivi du fichier ordinaire et du fichier de lien, vous pouvez voir la différence entre les deux.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <dirent.h>
//软连接,硬连接
//stat   函数与 lstat 函数的区别: 
//当一个文件是符号链接时,lstat 函数返回的是该符号链接本身的信息;而 stat 函数返回的是该链接指向文件的信息。
int main(int argc,char* argv[])
{	
	//保存访问前的时间
 	struct stat buf_save={};
 	if(stat(argv[1],&buf_save)==-1)   //int stat(const char *path, struct stat *buf);
 	{
 	 	fprintf(stderr,"%s\n",strerror(errno));
  		return 0;
 	}
//打开文件,写入hello
 	char str_hello[]="hello";
 	int fd = open(argv[1],O_WRONLY,S_IRWXU)
 	if(write(fd,str_hello,strlen(str_hello))==-1)
 	{
  		fprintf(stderr,"%s\n",strerror(errno));
 	}
 //int utime(const char *filename, const struct utimbuf *times);
// struct utimbuf timebuf={};
// time_t t =time(NULL);
// struct tm *p= gtime(&t);
//
// int link(const char *oldpath, const char *newpath);
// char *str="_link";
 	char temp1[20]="";
 	strcpy(temp1,argv[1]);
// strcat();
// link(argv[1], strcat(argv[1],str)); 
//
//stat 查看链接的文件
//lstat 本身
 	struct stat buf={};
 	stat(argv[1],&buf);
 	printf("stat的st_ino是 %ld\n",buf.st_ino);
 	struct stat lbuf={};
 	lstat(argv[1],&lbuf);
 	printf("lstat的st_ino是 %ld\n",lbuf.st_ino);
 	return 0;
}

3.11 Obtenez le chemin de travail du programme exécutable actuel et imprimez-le, puis modifiez les autorisations par défaut du fichier créé sous le chemin actuel. Tous les utilisateurs peuvent uniquement lire et créer un fichier

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <dirent.h>
int main(int argc ,char * argv[])
{
//获取当前路径
 	printf("1、获取当前工作路径------\n\n");
	//char *getcwd(char *buf, size_t size);
 	char buf[50]="";
 	getcwd(buf,50*sizeof(char));
 	printf("使用getcwd()测得的工作路径是:\n");
 	printf("%s\n",buf); 
// char *getwd(char *buf);
	char buf1[50]="";
	getwd(buf1);
	printf("使用getwd()测得的工作路径是:\n");
	printf("%s\n",buf1);
	//char *get_current_dir_name(void);
	char* buf2=get_current_dir_name();
	printf("使用get_current_dir_name()测得的工作路径是:\n");
	printf("%s\n",buf2);
//调用系统system();
 	printf("使用PWD测得的工作路径是:\n");
 	system("pwd");
//2、设置umask
 	printf("\n\n2、设置umask值,限制创建 只能是-w--w--w-\n\n");
 	mode_t modenew=0555;
 	umask(modenew);
 	printf("已设置umask=%o\n\n",modenew);
//3、创建文件
 	printf("3、创建文件,并查看文件属性\n\n");
 	int fd =open(argv[1],O_CREAT|O_TRUNC,0664);
 	close(fd);
 	system("ls -l");
 	return 0;
}

résultat de l'opération:

3.11

3.12 Implémentez votre propre myshell, et redirigez les résultats des commandes exécutées vers un fichier

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <dirent.h>
//    argv[0]  argv[1]  argv[2]
//   ./main     ls     -l
int main(int argc,char **argv)
{
//1、接受shell命令
 	char buffer[20]="";
 	if(argc>=2)
 	{
		int i=1;
		int len=0;
		strcpy(buffer,argv[1]);
		len=strlen(argv[1]);
		buffer[len]=' ';//用空格分隔
		for(i=2;i<=argc-1;i++)
  		{
   			strcat(buffer,argv[i]);
   			len=strlen(buffer);
   			buffer[len]=' ';//用空格分隔 
  		}
  		printf("\n\n----------得到的命令字符串%s-----------\n",buffer);
	}
//2、重定向
	//保存,int dup(int oldfd);
	int save_val=dup(1);//1 stdout
	//重定向,int dup2(int oldfd, int newfd);
	int res = dup2(1,"h3out.txt");
	if(res==-1)
	{
		fprintf(stderr,"%s\n",strerror(errno));
		return 0;
	}
//3、执行命令
	system(buffer);
	printf("-------------------------------------\n\n");
	return 0;
}

Insérez la description de l'image ici

Je suppose que tu aimes

Origine blog.csdn.net/Kshine2017/article/details/85336176
conseillé
Classement