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)
-
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 -
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). -
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) -
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 .
- E / S de entrada y salida estándar. El archivo de encabezado es "stdio.h".
- Tome fopen como ejemplo, use el comando man fopen para ver la información.
- 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. - 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. - 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é .
- 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)
- Abra el archivo especificado.
- 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.
- Con lseek, mueva el puntero de compensación al frente.
- Lea los datos que acaba de escribir nuevamente.
- 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:
- franco
- 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:
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.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;
}