1、open函数
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
int main(int argc, char *argv[])
{
int fd = open("./mydir", O_WRONLY);
printf("fd = %d, errno = %d\n", fd, errno);
if (fd == -1)
{
printf("%s\n", strerror(errno));
}
int fd1 = close(fd);
printf("fd1 = %d\n", fd1);
if (fd1 == -1)
{
printf("%s\n", strerror(errno));
}
return 0;
}
2、实现cp-系统函数
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
int main(int args, char *argv[])
{
// 1、打开要复制的文件
int fd1 = open(argv[1], O_RDONLY);
if (fd1 == -1)
printf("%s\n", strerror(errno));
// 2、新建1个空文件
int fd2 = open(argv[2], O_RDWR | O_CREAT | O_TRUNC, 0644);
if (fd2 == -1)
printf("%s\n", strerror(errno));
// 循环3、4、读文件到末尾read返回0
int counts1;
char buf[BUFSIZ];
while (1)
{
// 3、读取该文件
counts1 = read(fd1, buf, BUFSIZ);
// 4、读取到的内容写到空文件中
write(fd2, buf, counts1);
if (counts1 == 0)
break;
}
// 5、关闭打开的文件
close(fd1);
close(fd2);
return 0;
}
2、实现cp-库函数
#include <stdio.h>
int main(int argc, char *argv[])
{
// 1、只读方式打开文件
FILE * f1 = fopen(argv[1], "r");
// 2、创建新文件
FILE * f2 = fopen(argv[2], "w");
char buf[1];
int n; //读到的字节数
// 循环3、4、
while (1)
{
// 3、读文件存到缓冲区
n = fgetc(f1);
// 4、写到新文件中
fputc(n, f2);
if (n == EOF)
break;
}
fclose(f1);
fclose(f2);
return 0;
}
3、read读设备文件、网络文件、管道文件会阻塞
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char buf[10];
int n;
int flags = fcntl(STDIN_FILENO, F_GETFL);
if (flags == -1)
{
perror("fcntl STDIN_FILENO");
exit(1);
}
flags |= O_NONBLOCK;
int ret = fcntl(STDIN_FILENO, F_SETFL, flags);
if (ret == -1)
{
perror("fcntl STDIN_FILENO");
exit(1);
}
tryagain:
n = read(STDIN_FILENO, buf, 10);
if (n < 0)
{
if (errno != EAGAIN)
{
perror("read /dev/tty");
exit(1);
}
else
{
write(STDOUT_FILENO, "try again\n", strlen("try again\n"));
sleep(2);
goto tryagain;
}
}
write(STDOUT_FILENO, buf, n);
return 0;
}
4、lseek重新制定read write的偏移位置
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
int main(void)
{
int fd, n;
char msg[] = "It's a test for lseek\n";
char ch;
fd = open("lseek.txt", O_RDWR | O_CREAT, 0644);
if (fd < 0)
{
perror("open lseek.txt");
exit(1);
}
write(fd, msg, strlen(msg));
lseek(fd, 0, SEEK_SET);
while ((n = read(fd, &ch, 1))) // 1个1个字符往外读
{
if (n < 0)
{
perror("read error");
exit(1);
}
write(STDOUT_FILENO, &ch, n); // 1个1个字符往屏幕上写
}
close(fd);
return 0;
}
4、lseek结合实际IO写入-获取文件及扩展文件大小
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
int main(void)
{
int fd;
off_t n;
fd = open("lseek.txt", O_RDWR);
if (fd < 0)
{
perror("open lseek.txt");
exit(1);
}
n = lseek(fd, 0, SEEK_END);
printf("文件大小 = %ld\n", n);
printf("扩展1000字节\n");
n = lseek(fd, 1000 - 1, SEEK_END);
printf("文件大小 = %ld\n", n);
// 真正拓展文件大小-引起文件IO操作
write(fd, "\n", 1);
close(fd);
return 0;
}
5、trunctate拓展文件
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <errno.h>
#include <stdlib.h>
int main(void)
{
int n = truncate("./dict.txt", 1000);
if (n == -1)
{
perror("truncate error");
exit(1);
}
return 0;
}
6、stat获取文件属性(默认穿透)
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int ret;
struct stat buf;
ret = stat(argv[1], &buf);
if (ret == -1)
{
perror("stat error");
exit(1);
}
// 打印信息
printf("size = %ld, inode = %ld\n", buf.st_size, buf.st_ino);
// 判断文件类型
switch (buf.st_mode & S_IFMT)
{
case S_IFLNK :
printf("软链接文件\n");
break;
case S_IFREG :
printf("普通文件\n");
break;
case S_IFBLK :
printf("块设备文件\n");
break;
case S_IFSOCK :
printf("套接字文件\n");
break;
case S_IFDIR :
printf("目录文件\n");
break;
case S_IFCHR :
printf("字符设备文件\n");
break;
case S_IFIFO :
printf("管道文件\n");
break;
default:
printf("未知文件类型\n");
break;
};
return 0;
}
6、lstat获取文件属性(不穿透)
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int ret;
struct stat buf;
ret = lstat(argv[1], &buf);
if (ret == -1)
{
perror("stat error");
exit(1);
}
// 打印信息
printf("size = %ld, inode = %ld\n", buf.st_size, buf.st_ino);
// 判断文件类型
switch (buf.st_mode & S_IFMT)
{
case S_IFLNK :
printf("软链接文件\n");
break;
case S_IFREG :
printf("普通文件\n");
break;
case S_IFBLK :
printf("块设备文件\n");
break;
case S_IFSOCK :
printf("套接字文件\n");
break;
case S_IFDIR :
printf("目录文件\n");
break;
case S_IFCHR :
printf("字符设备文件\n");
break;
case S_IFIFO :
printf("管道文件\n");
break;
default:
printf("未知文件类型\n");
break;
};
return 0;
}
7、利用link和ulink实现mv
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(int args, char *argv[])
{
int ret1 = link(argv[1], argv[2]);
if (ret1 == -1)
{
perror("link error");
exit(1);
}
int ret2 = unlink(argv[1]);
if (ret2 == -1)
{
perror("link error");
exit(1);
}
return 0;
}
8、getcwd获取当前工作目录 和chdir改变工作目录
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
char buf[1024];
char * str = getcwd(buf, 1024);
if (str == NULL)
{
perror("getcwd error");
exit(1);
}
printf("当前工作目录在%s\n", buf);
int ret2 = chdir(argv[1]);
if (ret2 == -1)
{
perror("chdir error");
exit(1);
}
str = getcwd(buf, 1024);
if (str == NULL)
{
perror("getcwd error");
exit(1);
}
printf("当前工作目录在%s\n", buf);
return 0;
}
9、readdir实现ls(无递归)
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
#include <stdlib.h>
// 判断文件类型
int IsDir(const char *str)
{
int ret;
struct stat buf;
ret = stat(str, &buf);
if (ret == -1)
{
perror("stat error");
return -1; // 判断失败
}
if (S_ISDIR(buf.st_mode))
return 1; // 是目录
else
return 0; // 其他文件类型
}
void LS(const char *path)
{
int ret1 = IsDir(path);
if (ret1 != 1)
printf("%s ", path); // 非目录直接打印
else // 目录--
{
// 1、打开目录
DIR * dp = opendir(path);
if (dp == NULL)
{
perror("opendir error");
exit(1);
}
// 2、循环的读目录
struct dirent * dbuf;
while ((dbuf = readdir(dp)) != NULL)
{
// ls默认隐藏.开头的文件
if (dbuf->d_name[0] != '.')
printf("%s ", dbuf->d_name);
}
// 3、关闭目录
int ret2 = closedir(dp);
if (ret2 == -1)
{
perror("closedir error");
exit(1);
}
}
return ;
}
int main(int argc, char *argv[])
{
if (argc == 1)
LS("./");
else
{
for (int i = 1; i < argc; ++i)
LS(argv[i]);
}
return 0;
}
9、readdir实现ls(递归)
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
#include <stdlib.h>
// 判断文件类型
int IsDir(const char *str)
{
int ret;
struct stat buf;
ret = stat(str, &buf);
if (ret == -1)
{
perror("stat error");
return -1; // 判断失败
}
if (S_ISDIR(buf.st_mode))
return 1; // 是目录
else
return 0; // 其他文件类型
}
void LS(const char *path)
{
int ret1 = IsDir(path);
if (ret1 != 1)
printf("%s\n", path); // 非目录直接打印
else // 目录--
{
// 1、打开目录
DIR *dp = opendir(path);
if (dp == NULL)
{
perror("opendir error");
exit(1);
}
// 2、循环的读目录
struct dirent *dbuf;
while ((dbuf = readdir(dp)) != NULL)
{
// ls默认隐藏.开头的文件
if (dbuf->d_name[0] == '.')
continue;
// 1、判断读出来的文件是目录?
if (dbuf->d_type == DT_DIR)
{
// 2、是目录-递归调用自己
// 拼接绝对路径
printf("%s\t", dbuf->d_name);
char pj[BUFSIZ];
sprintf(pj, "%s%s%s", path, "/", dbuf->d_name);
// printf("pj = %s\n", pj);
LS(pj);
printf("\n");
}
// 2、不是目录-打印-读下一个目录项
else
{
if (dbuf->d_name[0] != '.')
printf("%s\t", dbuf->d_name);
}
}
// 3、关闭目录
int ret2 = closedir(dp);
if (ret2 == -1)
{
perror("closedir error");
exit(1);
}
}
return;
}
int main(int argc, char *argv[])
{
if (argc == 1)
LS("./");
else
{
for (int i = 1; i < argc; ++i)
LS(argv[i]);
}
return 0;
}
10、dup和dup2重定向文件描述符
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
int main(int argc, char *argv[])
{
int fd1 = open(argv[1], O_RDWR | O_APPEND);
if (fd1 == -1)
{
perror("open error");
exit(1);
}
printf("fd1 = %d\n", fd1);
int fd2 = dup(fd1);
printf("fd2 = %d\n", fd2);
// read write共用同一个位置(追加O_APPEND/lseek SEEK_END设置写入位置为末尾)
int ret2 = write(fd1, "old write\n", 10);
if (ret2 == -1)
{
perror("old write");
exit(1);
}
int ret3 = write(fd2, "----test----\n", 13);
if (ret3 == -1)
{
perror("write error");
exit(1);
}
int ret4 = close(fd1);
if (ret4 == -1)
{
perror("close error");
exit(1);
}
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
int main(int argc, char *argv[])
{
int fd1 = open(argv[1], O_RDWR | O_APPEND);
if (fd1 == -1)
{
perror("open error");
exit(1);
}
printf("旧fd1 = %d\n", fd1);
int fd2 = open(argv[2], O_RDWR | O_APPEND);
if (fd2 == -1)
{
perror("open error");
exit(1);
}
printf("新fd2 = %d\n", fd2);
int ret1 = dup2(fd1, fd2);
if (ret1 == -1)
{
perror("dup2 error");
exit(1);
}
printf("dup2返回值 = %d\n", ret1);
// read write共用同一个位置(追加O_APPEND/lseek SEEK_END设置写入位置为末尾)
int ret2 = write(fd1, "old write\n", 10);
if (ret2 == -1)
{
perror("old write");
exit(1);
}
int ret3 = write(fd2, "----test----\n", 13);
if (ret3 == -1)
{
perror("write error");
exit(1);
}
int ret4 = close(fd1);
if (ret4 == -1)
{
perror("close error");
exit(1);
}
return 0;
}
9、dup2重定向标准输出
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <errno.h>
int main(int argc, char *argv[])
{
int fd = open(argv[1], O_RDWR | O_APPEND);
if (fd == -1)
{
perror("open error");
exit(1);
}
int ret1 = dup2(fd, STDOUT_FILENO); // 重定向标准输出-打开的文件上
if (ret1 == -1)
{
perror("dup2 error");
exit(1);
}
printf("dup2返回值%d\n", ret1);
int i = 0;
while (i < 20)
{
printf("hello %d\n", i);
++i;
sleep(1);
}
return 0;
}
9、fcntl实现dup2
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
int fd1 = open(argv[1], O_RDWR | O_APPEND);
printf("fd1 = %d\n", fd1);
write(fd1, "the first write\n", 17);
int ret = fcntl(fd1, F_DUPFD, 0); // 返回1个新的文件描述符--类似dup(fd); dup2(fd1, fd2);
printf("newfd = %d\n", ret);
write(ret, "the second write\n", 18);
int ret1 = fcntl(fd1, F_DUPFD, 7); // 返回1个新的文件描述符--类似dup(fd); dup2(fd1, fd2);
printf("newfd1 = %d\n", ret1);
write(ret1, "the third write\n", 17);
write(7, "the third 7 write\n", 19);
return 0;
}