基于C,进一步研究 linux内核函数,系统级别的函数
201708xx
1、缓存
缓存是为了解决速度差的问题。
1.1 IO缓存(标准IO)
-
全缓存
磁盘文件。
刷新方式:(1)全缓存 8192字节,全缓存满了,会刷新;(2)fflush(文件流指针FILE*)。(3)fclose -
行缓存
标准输出stdout,标准输入 stdin。stdout—> printf();
刷新方式:(1)’\n’ ,将内容 物理输出到屏幕;(2)行缓存满了,1024字节;(3)fflush(stdout)。 -
无缓存
标准错误流stderr。
刷新方式:无刷新。
直接输出:
(1)perror(“XXX”);//会有一个success在后面
(2)fprintf(stderr,“XXX\n”);
(3)exit(0);//#include <stdlib.h> 执行时,会刷新IO (直接输出)
_Exit(0);//#include <stdlib.h> 执行时,会刷新IO (直接输出)
_exit(0);//#include <unistd.h> 不刷新IO(不会输出) -
缓存操作函数
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,默认采用了缓冲机制。
- 标准输入输出IO。头文件为“stdio.h”。
- 以fopen为例,man fopen命令查看信息。
- 打开文本(放到内存中)。
fopen: 打开一个文件,
建立了一个缓冲区(读写模式下将建立两个缓冲区),
并创建了一个包含文件和缓冲区相关数据的数据结构FILE。 - 操作文本。
可以操作二进制文件的是:fread fwrite
可以操作字符文件的是:fgets fputs fgetc fputc fscanf fprintf
一次读取的过程中,fscanf遇到空格和换行时结束,注意空格时也结束。这与fgets有区别,fgets遇到空格不结束。 - 关闭文本。
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。无缓存。
- 以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 将字符串的字母一个一个打印出来,要求不换行。
#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;
}
运行效果:字符串成员一个一个的被打印出来,(不是一下子被打印出来)。
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)操作
- 打开指定的文件。
- 向其中写入我的幸运数字23,此时文件的偏移指针已经后移。
- 通过lseek,将偏移指针移动到前面。
- 再次读取刚写入的数据。
- 最后关闭文件。
//标准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和port等式信息,提取出数值信息。
要求通过 系统IO,分解出192.168.1.1存入 第一个字符数组中,分解出8080 存入第二个字符数组中。最后打印输出。
- 先通过系统IO,向文件中写入信息。
- 再通过fdopen,转到标准IO的操作。
- 利用标准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,实现copy功能
要求文件名1,文件名2 从main的参数传入。
//标准库
#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 重定向
将九九乘法表打印到文件中,要求使用重定向。
重定向有两种方式:
- freopen
- 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 ,打开一个文件,权限为读写。如果文件不存在需要touch一个空文件出来。
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和access
使用umask函数将umask屏蔽值修改为:当前你所创建的文件都只写。
使用open 函数创建文件a.txt使文件的权限为rw—x-wx。
使用access判断该文件是否具有可写文件。
如果有可写文件,则使用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;
}
运行结果:
更规范的写法如下:
//递归打印路径
#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 函数的区别
在调用执行文件时,后面接普通文件和link文件,可以看到两者区别。
#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.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;
}