#Linux中のGCC规划#標準IOおよびシステムIO

Cに基づいて、Linuxカーネル関数、システムレベル関数をさらに研究する

201708xx

1.キャッシュ

キャッシュは速度低下の問題を解決するためのものです。

1.1 IOキャッシュ(標準IO)

  1. 完全なキャッシュ
    ディスクファイル。
    リフレッシュモード:(1)フルキャッシュが8192バイトで、フルキャッシュがフルで、リフレッシュされます;(2)fflush(ファイルストリームポインターFILE *)。(3)fclose

  2. ラインバッファの
    標準出力stdout、標準入力stdin。stdout—> printf();
    更新モード:(1) '\ n'、コンテンツの画面への物理出力、(2)ラインバッファーがいっぱい、1024バイト、(3)fflush(標準出力)。

  3. キャッシュ
    標準エラーストリームstderrはありません
    更新モード:更新なし。
    直接出力:
    (1)perror( "XXX"); //成功します
    (2)fprintf(stderr、 "XXX \ n");
    (3)exit(0); //#include <stdlib。 h>実行すると、IOが更新されます(直接出力)
    _Exit(0); //#include <stdlib.h>実行すると、IOが更新されます(直接出力)
    _exit(0); //#include <unistd.h> IOを更新しない(出力なし)

  4. キャッシュ操作関数
    setbuf(stdin、buffer); //キーボード入力の保存場所を変更

#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.標準IOおよびシステムIO

2.1 標準IOバッファメカニズムがデフォルトで使用されます

  1. 標準入出力IO。ヘッダーファイルは「stdio.h」です。
  2. 例としてfopenを取り上げ、man fopenコマンドを使用して情報を表示します。
  3. テキストを開きます(メモリに入れます)。
    fopen:ファイルを開き、
    バッファーを作成し(2つのバッファーは読み取り/書き込みモードで作成されます)、
    ファイルとバッファーに関連するデータを含むデータ構造FILEを作成します。
  4. 操作テキスト。
    バイナリファイルを操作できます:fread fwrite
    は文字ファイルを操作できます:fgets fputs fgetc fputc fscanf fprintf
    読み取りプロセス、fscanfはスペースと改行を検出すると終了し、スペースに注意を払うと終了します。これは、スペースに遭遇しても終了しないfgetsとは異なります。
  5. テキストを閉じます。
    fclose:ファイルを閉じてキャッシュを更新します。テキストデータをメモリにローカルに配置します。
#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 システムIO、ファイルIO、低レベルIOとも呼ばれます。キャッシュなし

  1. 例としてopenを取り上げ、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.いくつかのテストコード

3.1折り返さずに、文字列の文字を1つずつ印刷します。

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

操作効果:文字列メンバーが1つずつ(一度にすべてではなく)出力されます。

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システムIO(テキストIO)操作

  1. 指定されたファイルを開きます。
  2. ラッキーナンバー23を書いてくださいこの時点で、ファイルのオフセットポインタが後方に移動しています。
  3. lseekを使用して、オフセットポインターを前面に移動します。
  4. 書き込んだばかりのデータを再度読み取ります。
  5. 最後にファイルを閉じます。
//标准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;
}

演算結果:

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システムIO +標準IO、IPおよびポート方程式の情報をファイルに書き込み、数値情報を抽出します。

システムIOを介して192.168.1.1を分解して最初の文字配列に格納し、8080に分解して2番目の文字配列に格納する必要があります。最後に印刷します。

  • まず、システムIOを介してファイルに情報を書き込みます。
  • もう一度渡すfdopen、標準入出力の操作に進みます。
  • 標準IOを使用して、オフセットポインターをファイルの先頭に戻します。
  • ファイル情報を読み、それを抽出します。
  • ファイルを閉じる
//标准库
#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;
}

演算結果:

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システムIO、コピー機能の実現

ファイル名1、ファイル名2をメインパラメータから渡す必要があります。

//标准库
#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リダイレクト

リダイレクトを必要とする、九九九九九九をファイルに出力します。
リダイレクトするには2つの方法があります。

  1. フレオープン
  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;
}

演算結果:

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システムIO、開いているファイルの権限を変更する

1.読み取りおよび書き込み権限でファイルを開きます。ファイルが存在しない場合は、空のファイルをタッチする必要があります。
2. fcntlで「追加」権限を増やします。
3.書き込むhelloworldを追加します。最終的なファイルにhelloworldがあります。

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

演算結果

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システムIO、umask、アクセス

使用するumask関数umaskマスク値を次のように変更します。作成したファイルは現在書き込み専用です。
使用するオープン機能a.txtファイルを作成して、ファイル権限をrw-x-wxにします。
使用するアクセスファイルに書き込み可能なファイルがあるかどうかを確認します。
書き込み可能なファイルがある場合は、chmodを使用してユーザーの書き込み可能なファイルを削除します。

#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ファイル名でファイルタイプを判断する

//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指定したディレクトリとそのサブディレクトリ内のすべてのファイル名を表示する

再帰呼び出しを使用する

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

演算結果:
3.9ディレクトリ構造の表示

より標準化された記述方法は次のとおりです。

//递归打印路径
#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 stat関数とlstat関数の違い

実行可能ファイルを呼び出してから、通常ファイルとリンクファイルを呼び出すと、両者の違いを確認できます。

#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現在の実行可能プログラムの作業パスを取得して印刷し、現在のパスの下に作成されたファイルのデフォルトのアクセス許可を変更します。すべてのユーザーはファイルの読み取りと作成のみが可能です

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

演算結果:

3.11

3.12独自のmyshellを実装し、実行したコマンドの結果をファイルにリダイレクトする

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

ここに画像の説明を挿入

おすすめ

転載: blog.csdn.net/Kshine2017/article/details/85336176