#Linux中的GCC规划# Standard IO and System IO

Based on C, further study linux kernel functions, system-level functions

201708xx

1. Cache

The cache is to solve the problem of poor speed.

1.1 IO cache (standard IO)

  1. Full cache
    disk file.
    Refresh mode: (1) the full cache is 8192 bytes, and the full cache is full, it will be refreshed; (2) fflush (file stream pointer FILE*). (3) fclose

  2. Line buffer
    standard output stdout, standard input stdin. stdout—> printf();
    Refresh mode: (1)'\n', physical output of the content to the screen; (2) the line buffer is full, 1024 bytes; (3) fflush (stdout).

  3. No cache
    standard error stream stderr.
    Refresh mode: no refresh.
    Direct output:
    (1) perror("XXX");//There will be a success in the back
    (2) fprintf(stderr,"XXX\n");
    (3) exit(0);//#include <stdlib. h> When executed, IO will be refreshed (direct output)
    _Exit(0);//#include <stdlib.h> When executed, IO will be refreshed (direct output)
    _exit(0);//#include <unistd.h> Do not refresh IO (no output)

  4. Cache operation function
    setbuf(stdin,buffer);//Change the storage location of keyboard input

#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. Standard IO and system IO

2.1 Standard IO, The buffer mechanism is used by default .

  1. Standard input and output IO. The header file is "stdio.h".
  2. Take fopen as an example, use the man fopen command to view information.
  3. Open the text (put it in memory).
    fopen: Open a file,
    create a buffer (two buffers will be created in the read-write mode),
    and create a data structure FILE that contains file and buffer related data.
  4. Operation text.
    Binary files can be manipulated: fread fwrite
    can manipulate character files: fgets fputs fgetc fputc fscanf fprintf During
    a reading process, fscanf ends when it encounters a space and a newline, and it also ends when you pay attention to a space. This is different from fgets, which does not end when it encounters a space.
  5. Close the text.
    fclose: Close the file and refresh the cache. Put the text data in the memory to the 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 System IO, Also called file IO, low-level IO. No cache .

  1. Take open as an example, check the corresponding information through 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. Some test codes

3.1 Print out the letters of the string one by one, without wrapping.

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

Operation effect: string members are printed out one by one (not all at once).

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 System IO (text IO) operation

  1. Open the specified file.
  2. Write my lucky number 23 into it. At this time, the offset pointer of the file has moved backward.
  3. With lseek, move the offset pointer to the front.
  4. Read the data just written again.
  5. Finally close the file.
//标准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;
}

operation result:

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, write ip and port equation information to the file, and extract the numerical information.

It is required to decompose 192.168.1.1 through the system IO and store it in the first character array, and decompose it to 8080 and store it in the second character array. Finally print out.

  • First, write information to the file through the system IO.
  • Pass againfdopen, Go to the operation of standard IO.
  • Using standard IO, move the offset pointer back to the beginning of the file.
  • Read the file information and extract it.
  • Close file
//标准库
#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;
}

operation result:

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 System IO, realize copy function

Requires file name 1, file name 2 to be passed in from the main parameter.

//标准库
#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 Redirect

Print the nine-nine-nine multiplication table to a file, requiring redirection.
There are two ways to redirect:

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

operation result:

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, modify the permissions of opened files

1. Open a file with read and write permissions. If the file does not exist, you need to touch an empty file.
2. Increase the "append" permission through fcntl.
3. Add helloworld to be written, and there is helloworld in the final file.

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

operation result

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 and access

useumask functionModify the umask mask value to: the files you create are currently only write.
useopen functionCreate the file a.txt to make the file permissions rw-x-wx.
useaccessDetermine whether the file has a writable file.
If there are writable files, use chmod to delete the user's writable files.

#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 Judge file type by file name

//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 Display all file names in the specified directory and its subdirectories

Use recursive calls

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

operation result:
3.9 Display directory structure

A more standardized way of writing is as follows:

//递归打印路径
#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 The difference between stat function and lstat function

When calling the executable file, followed by the ordinary file and the link file, you can see the difference between the two.

#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 Obtain the working path of the current executable program and print it out, and then modify the default permissions of the created file under the current path. All users can only read only and create a file

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

operation result:

3.11

3.12 Implement your own myshell, and redirect the results of the executed commands to a file

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

Insert picture description here

Guess you like

Origin blog.csdn.net/Kshine2017/article/details/85336176