#Linux 中 的 GCC 规划 # E / S estándar y E / S del sistema

Basado en C, estudiar más a fondo las funciones del kernel de Linux, funciones a nivel de sistema

201708xx

1. Caché

El caché sirve para solucionar el problema de la baja velocidad.

1.1 caché de E / S (E / S estándar)


  1. Archivo de disco de caché completo .
    Modo de actualización: (1) la caché completa es de 8192 bytes, y la caché completa está llena, se actualizará; (2) fflush (puntero de flujo de archivo FILE *). (3) fcerrar

  2. Búfer de línea
    salida estándar stdout, entrada estándar stdin. stdout—> printf ();
    Modo de actualización: (1) '\ n', salida física del contenido a la pantalla; (2) el búfer de línea está lleno, 1024 bytes; (3) fflush (stdout).

  3. Sin caché
    estándar stderr secuencia de errores.
    Modo de actualización: sin actualización.
    Salida directa:
    (1) perror ("XXX"); // Habrá un éxito en la parte posterior
    (2) fprintf (stderr, "XXX \ n");
    (3) exit (0); // # include <stdlib. h> Cuando se ejecuta, IO se actualizará (salida directa)
    _Salir (0); // # incluir <stdlib.h> Cuando se ejecuta, IO se actualizará (salida directa)
    _exit (0); // # incluir <unistd.h> No actualizar IO (sin salida)

  4. Función de operación de caché
    setbuf (stdin, buffer); // Cambiar la ubicación de almacenamiento de la entrada del teclado

#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 estándar y E / S del sistema

2.1 IO estándar, El mecanismo de búfer se utiliza de forma predeterminada .

  1. E / S de entrada y salida estándar. El archivo de encabezado es "stdio.h".
  2. Tome fopen como ejemplo, use el comando man fopen para ver la información.
  3. Abre el texto (ponlo en memoria).
    fopen: Abra un archivo,
    cree un búfer (se crearán dos búferes en el modo de lectura y escritura)
    y cree un ARCHIVO de estructura de datos que contenga datos relacionados con el archivo y el búfer.
  4. Texto de operación.
    Los archivos binarios se pueden manipular: fread fwrite
    puede manipular archivos de caracteres: fgets fputs fgetc fputc fscanf fprintf Durante
    un proceso de lectura, fscanf finaliza cuando encuentra un espacio y una nueva línea, y también finaliza cuando prestas atención a un espacio. Esto es diferente de fgets, que no termina cuando se encuentra con un espacio.
  5. Cierra el texto.
    fclose: cierra el archivo y actualiza la caché. Ponga los datos de texto en la memoria al 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 E / S del sistema, También llamado archivo IO, IO de bajo nivel. Sin caché .

  1. Tome open como ejemplo, verifique la información correspondiente a través de 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. Algunos códigos de prueba

3.1 Imprime las letras de la cadena una a una, sin envolver.

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

Efecto de la operación: los miembros de la cadena se imprimen uno por uno (no todos a la vez).

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 Operación System IO (text IO)

  1. Abra el archivo especificado.
  2. Escriba en él mi número de la suerte 23. En este momento, el puntero de desplazamiento del archivo se ha movido hacia atrás.
  3. Con lseek, mueva el puntero de compensación al frente.
  4. Lea los datos que acaba de escribir nuevamente.
  5. Finalmente cierre el archivo.
//标准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;
}

resultado de la operación:

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 E / S del sistema + E / S estándar, escriba la información de la ecuación del puerto y la ip en el archivo y extraiga la información numérica.

Es necesario descomponer 192.168.1.1 a través de la E / S del sistema y almacenarlo en la primera matriz de caracteres, descomponerlo en 8080 y almacenarlo en la segunda matriz de caracteres. Finalmente imprímalo.

  • Primero, escriba información en el archivo a través del sistema IO.
  • Pasa otra vezfdopen, Vaya al funcionamiento de E / S estándar.
  • Utilizando E / S estándar, mueva el puntero de compensación al principio del archivo.
  • Lea la información del archivo y extráigala.
  • Cerrar el archivo
//标准库
#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;
}

resultado de la operación:

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 Sistema IO, realizar la función de copia

Requiere que el nombre de archivo 1, el nombre de archivo 2 se pasen desde el parámetro 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 Redirigir

Imprima la tabla de multiplicar nueve-nueve-nueve en un archivo, lo que requiere redirección.
Hay dos formas de redireccionar:

  1. franco
  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;
}

resultado de la operación:

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, modificar los permisos de archivos abiertos

1. Abra un archivo con permisos de lectura y escritura. Si el archivo no existe, debe tocar un archivo vacío.
2. Aumente el permiso "agregar" a través de fcntl.
3. Agregue helloworld para que se escriba y aparecerá helloworld en el archivo 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;
}

resultado de la operación

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 y acceso

utilizarfunción umaskModifique el valor de la máscara de umask a: los archivos que crea actualmente solo se escriben.
utilizarfunción abiertaCree el archivo a.txt para que los permisos de archivo sean rw-x-wx.
utilizaraccesoDetermine si el archivo tiene un archivo grabable.
Si hay archivos grabables, use chmod para eliminar los archivos grabables del usuario.

#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 Juzgar tipo de archivo por nombre de archivo

//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 Mostrar todos los nombres de archivos en el directorio especificado y sus subdirectorios

Usa llamadas recursivas

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

resultado de la operación:
3.9 Mostrar estructura de directorios

Una forma de escritura más estandarizada es la siguiente:

//递归打印路径
#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 diferencia entre la función stat y la función lstat

Al llamar al archivo ejecutable, seguido del archivo ordinario y el archivo de enlace, puede ver la diferencia entre los dos.

#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 Obtenga la ruta de trabajo del programa ejecutable actual e imprímalo, y luego modifique los permisos predeterminados del archivo creado en la ruta actual. Todos los usuarios solo pueden leer y crear un archivo

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

resultado de la operación:

3.11

3.12 Implemente su propio myshell y redirija los resultados de los comandos ejecutados a un archivo

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

Inserte la descripción de la imagen aquí

Supongo que te gusta

Origin blog.csdn.net/Kshine2017/article/details/85336176
Recomendado
Clasificación