本文共 11393 字,大约阅读时间需要 37 分钟。
文件和I/O
STDIN_FILENO stdin
STDOUT_FILENO stdout
STDERROR_FILENO stderr
一、文件描述符
q 对于Linux而言,所有对设备或文件的操作都是通过文件描述符进行的。
q 当打开或者创建一个文件的时候,内核向进程返回一个文件描述符(非负整数)。后续对文件的操作只需通过该文件描述符,内核记录有关这个打开文件的信息。
q 一个进程启动时,默认打开了3个文件,标准输入、标准输出、标准错误,对应文件描述符是0(STDIN_FILENO)、1(STDOUT_FILENO)、2(STDERR_FILENO),这些常量定义在unistd.h头文件中。
二、文件描述符与文件指针转换
q fileno:将文件指针转换为文件描述符
q fdopen:将文件描述符转换为文件指针
//01fileno.c
#include<stdio.h>
#include<stdlib.h>
intmain()
{
printf(“fileno(stdin):%d\n”,fileno(stdin));
return 0;
}
三、open函数
//01open.c
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdlib.h>
#include<stdio.h>
#include<errno.h>
#include<string.h>
/*
#defineERR_EXIT(m) (perror(m), exit(EXIT_FAILURE))
*/
#defineERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while(0)
intmain(void)
{
int fd;
fd = open("test.txt",O_RDONLY);
/*
if (fd == -1)
{
fprintf(stderr, "openerror with errno=%d %s\n", errno, strerror(errno));
exit(EXIT_FAILURE);
}
*/
/*
if (fd == -1)
{
perror("openerror");
exit(EXIT_FAILURE);
}
*/
if (fd == -1)
ERR_EXIT("openerror");
printf("open succ\n");
return 0;
}
//02open.c
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdlib.h>
#include<stdio.h>
#include<errno.h>
#include<string.h>
#defineERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while(0)
intmain(void)
{
umask(0);
int fd;
fd = open("test.txt",O_WRONLY |O_CREAT, 0666);
if (fd == -1)
ERR_EXIT("openerror");
printf("open succ\n");
return 0;
}
//03open.c
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdlib.h>
#include<stdio.h>
#include<errno.h>
#include<string.h>
#defineERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while(0)
intmain(void)
{
umask(0);
int fd;
fd = open("test.txt",O_WRONLY | O_CREAT |O_EXCL, 0666);
if (fd == -1)
ERR_EXIT("openerror");
printf("open succ\n");
return 0;
}
//04open.c
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdlib.h>
#include<stdio.h>
#include<errno.h>
#include<string.h>
#defineERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while(0)
int main(void)
{
umask(0);
int fd;
fd = open("test2.txt",O_WRONLY | O_CREAT | O_EXCL,S_IRUSR |S_IWUSR);
if (fd == -1)
ERR_EXIT("openerror");
printf("open succ\n");
close(fd);
return 0;
}
四、man 2 open查看相关的属性
1、打开文件的方式
2、访问权限
打开方式 | 描述 |
S_IRUSR | 文件所有者的读权限位 |
S_IWUSR | 文件所有者的写权限位 |
S_IXUSR | 文件所有者的执行权限位 |
S_IRWXU | S_IRUSR|S_IWUSR|S_IXUSR |
S_IRGRP | 文件用户组的读权限位 |
S_IWGRP | 文件用户组的写权限位 |
S_IXGRP | 文件用户组的执行权限位 |
S_IRWXG | S_IRGRP|S_IWGRP|S_IXGRP |
S_IROTH | 文件其他用户的读权限位 |
S_IWOTH | 文件其他用户的写权限位 |
S_IXOTH | 文件其他用户的执行权限位 |
S_IRWXO | S_IROTH|S_IWOTH|S_IXOTH |
五、open调用的几点说明
q 可以利用按位逻辑加(bitwise-OR)(|)对打开方式的标志值进行组合。
如打开一个新文件:
#define NEWFILE (O_WRONLY|O_CREAT|O_TRUNC)
q 对访问权限位进行访问所用到的标识符,均可以通过
#include <sys/stat.h>访问到,同样可以通过|运算来对访问权限进行组合
#define MODE755 (S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)
六、close系统调用
q 为了重新利用文件描述符,用close()系统调用释放打开的文件描述符
函数原型:int close(int fd);
函数参数:
- fd :要关闭的文件的文件描述符
返回值
如果出现错误,返回-1
调用成功返回0
七、read系统调用
q 一旦有了与一个打开文件描述相连的文件描述符,只要该文件是用O_RDONLY或O_RDWR标志打开的,就可以用read()系统调用从该文件中读取字节
q 函数原型:
ssize_t read(int fd, void*buf, size_t count);
参数
q fd:想要读的文件的文件描述符
q buf:指向内存块的指针,从文件中读取来的字节放到这个内存块中
q count:从该文件复制到buf中的字节个数
返回值
如果出现错误,返回-1
读文件结束,返回0
否则返回从该文件复制到规定的缓冲区中的字节数
八、write系统调用
q 用write()系统调用将数据写到一个文件中
函数原型:
ssize_twrite(int fd, const void *buf, size_t count);
函数参数:
- fd:要写入的文件的文件描述符
- buf:指向内存块的指针,从这个内存块中读取数据写入 到文件中
- count:要写入文件的字节个数
返回值
如果出现错误,返回-1
如果写入成功,则返回写入到文件中的字节个数
//01cp.c
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdlib.h>
#include<stdio.h>
#include<errno.h>
#include<string.h>
#defineERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while(0)
intmain(int argc, char *argv[])
{
int infd;
int outfd;
if (argc != 3)
{
fprintf(stderr, "Usage%s src dest\n", argv[0]);
exit(EXIT_FAILURE);
}
infd = open(argv[1], O_RDONLY);
if (infd == -1)
ERR_EXIT("open srcerror");
if ((outfd = open(argv[2], O_WRONLY |O_CREAT | O_TRUNC, 0644)) == -1)
ERR_EXIT("open desterror");
char buf[1024];
int nread;
while ((nread = read(infd, buf, 1024))> 0)
{
write(outfd, buf, nread);
}
close(infd);
close(outfd);
return 0;
}
read可以保证一定能读到缓冲区
write不能保证一定能从缓冲区写到文件中,除非调用int fsync(int fd)函数或在打开文件时指定O_SYNC
九、lseek调用
//01lseek.c
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdlib.h>
#include<stdio.h>
#include<errno.h>
#include<string.h>
#defineERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while(0)
intmain(void)
{
int fd;
fd = open("test.txt",O_RDONLY);
if (fd == -1)
ERR_EXIT("openerror");
char buf[1024] = {0};
int ret = read(fd, buf, 5);
if (ret == -1)
ERR_EXIT("readerror");
printf("buf=%s\n", buf);
ret = lseek(fd, 0, SEEK_CUR);
if (ret == -1)
ERR_EXIT("lseek");
printf("current offset=%d\n",ret);
return 0;
}
//03hole.c
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdlib.h>
#include<stdio.h>
#include<errno.h>
#include<string.h>
#defineERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while(0)
intmain(void)
{
int fd;
fd = open("hole.txt",O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (fd == -1)
ERR_EXIT("openerror");
write(fd, "ABCDE", 5);
int ret = lseek(fd, 32, SEEK_CUR);
if (ret == -1)
ERR_EXIT("lseekerror");
write(fd, "hello", 5);
close(fd);
return 0;
}
man lseek
od –chole.txt 查看hole.txt在内存中的使用情况
du –hhole.txt 查看hole.txt在磁盘占用的情况
十、opendir、readdir调用
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdlib.h>
#include<stdio.h>
#include<errno.h>
#include<string.h>
#include<dirent.h>
#defineERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while(0)
intmain(void)
{
DIR *dir = opendir(".");
struct dirent *de;
while ((de = readdir(dir)) != NULL)
{
if (strncmp(de->d_name,".", 1) == 0)
continue;
printf("%s\n",de->d_name);
}
closedir(dir);
exit(EXIT_SUCCESS);
}
十一、stat函数
#include<unistd.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdlib.h>
#include<stdio.h>
#include<errno.h>
#include<string.h>
#defineERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while(0)
#defineMAJOR(a) (int)((unsigned short)a >> 8)
#defineMINOR(a) (int)((unsigned short)a & 0xFF)
intfiletype(struct stat *buf);
voidfileperm(struct stat *buf, char *perm);
intmain(int argc, char *argv[])
{
if (argc != 2)
{
fprintf(stderr, "Usage%s file\n", argv[0]);
exit(EXIT_FAILURE);
}
struct stat sbuf;
printf("Filename:%s\n",argv[1]);
if (lstat(argv[1], &sbuf) == -1)
ERR_EXIT("staterror");
printf("File number:major %d,minor%d inode %d\n", MAJOR(sbuf.st_dev), MINOR(sbuf.st_dev), (int)sbuf.st_ino);
if (filetype(&sbuf))
{
printf("Devicenumber:major %d,minor %d\n", MAJOR(sbuf.st_rdev), MINOR(sbuf.st_rdev));
}
char perm[11] = {0};
fileperm(&sbuf, perm);
printf("File permission bits=%o%s\n", sbuf.st_mode & 07777, perm);
return 0;
}
intfiletype(struct stat *buf)
{
int flag = 0;
printf("Filetype:");
mode_t mode;
mode = buf->st_mode;
switch (mode & S_IFMT)
{
case S_IFSOCK:
printf("socket\n");
break;
case S_IFLNK:
printf("symboliclink\n");
break;
case S_IFREG:
printf("regularfile\n");
break;
case S_IFBLK:
printf("blockdevice\n");
flag = 1;
break;
case S_IFDIR:
printf("directory\n");
break;
case S_IFCHR:
printf("characterdevice\n");
flag = 1;
break;
case S_IFIFO:
printf("FIFO\n");
break;
default:
printf("unknown filetype\n");
break;
}
return flag;
}
voidfileperm(struct stat *buf, char *perm)
{
strcpy(perm, "----------");
perm[0] = '?';
mode_t mode;
mode = buf->st_mode;
switch (mode & S_IFMT)
{
case S_IFSOCK:
perm[0] = 's';
break;
case S_IFLNK:
perm[0] = 'l';
break;
case S_IFREG:
perm[0] = '-';
break;
case S_IFBLK:
perm[0] = 'b';
break;
case S_IFDIR:
perm[0] = 'd';
break;
case S_IFCHR:
perm[0] = 'c';
break;
case S_IFIFO:
perm[0] = 'p';
break;
}
if (mode & S_IRUSR)
perm[1] = 'r';
if (mode & S_IWUSR)
perm[2] = 'w';
if (mode & S_IXUSR)
perm[3] = 'x';
if (mode & S_IRGRP)
perm[4] = 'r';
if (mode & S_IWGRP)
perm[5] = 'w';
if (mode & S_IXGRP)
perm[6] = 'x';
if (mode & S_IROTH)
perm[7] = 'r';
if (mode & S_IWOTH)
perm[8] = 'w';
if (mode & S_IXOTH)
perm[9] = 'x';
perm[10] = '\0';
}
十二、一个进程打开两个文件
#include<unistd.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdlib.h>
#include<stdio.h>
#include<errno.h>
#include<string.h>
#defineERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while(0)
intmain(int argc, char *argv[])
{
int fd1;
int fd2;
char buf1[1024] = {0};
char buf2[1024] = {0};
fd1 = open("test.txt",O_RDONLY);
if (fd1 == -1)
ERR_EXIT("openerror");
read(fd1, buf1, 5);
printf("buf1=%s\n", buf1);
fd2 = open("test.txt",O_RDWR);
if (fd2 == -1)
ERR_EXIT("openerror");
read(fd2, buf2, 5);
printf("buf2=%s\n", buf2);
write(fd2, "AAAAA", 5);
memset(buf1, 0, sizeof(buf1));
read(fd1, buf1, 5);
printf("buf1=%s\n", buf1);
close(fd1);
close(fd2);
return 0;
}
十三、dup或dup2或fcntl进行输出重定向
#include<unistd.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdlib.h>
#include<stdio.h>
#include<errno.h>
#include<string.h>
#defineERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while(0)
intmain(int argc, char *argv[])
{
int fd;
fd = open("test2.txt",O_WRONLY);
if (fd == -1)
ERR_EXIT("openerror");
/*
close(1);
dup(fd);
*/
/*
dup2(fd, 1);
*/
close(1);
if (fcntl(fd, F_DUPFD, 0) < 0)
ERR_EXIT("dup fderror");
printf("hello\n");
return 0;
}
十四、文件状态标志
#include<unistd.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdlib.h>
#include<stdio.h>
#include<errno.h>
#include<string.h>
#defineERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while(0)
voidset_flag(int fd, int flags);
voidclr_flag(int fd, int flags);
intmain(int argc, char *argv[])
{
char buf[1024] = {0};
int ret;
/*
int flags;
flags = fcntl(0, F_GETFL, 0);
if (flags == -1)
ERR_EXIT("fcntl get flagerror");
ret = fcntl(0, F_SETFL, flags |O_NONBLOCK);
if (ret == -1)
ERR_EXIT("fcntl set flagerror");
*/
set_flag(0, O_NONBLOCK);
clr_flag(0, O_NONBLOCK);
ret = read(0, buf, 1024);
if (ret == -1)
ERR_EXIT("readerror");
printf("buf=%s\n", buf);
return 0;
}
voidset_flag(int fd, int flags)
{
int val;
val = fcntl(fd, F_GETFL, 0);
if (val == -1)
ERR_EXIT("fcntl get flagerror");
val |= flags;
if (fcntl(fd, F_SETFL, val) < 0)
ERR_EXIT("fcntl set flagerror");
}
voidclr_flag(int fd, int flags)
{
int val;
val = fcntl(fd, F_GETFL, 0);
if (val == -1)
ERR_EXIT("fcntl get flagerror");
val &= ~flags;
if (fcntl(fd, F_SETFL, val) < 0)
ERR_EXIT("fcntl set flagerror");
}
十五、文件锁(注意F_SETLK与F_SETLKW的区别)
#include<unistd.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdlib.h>
#include<stdio.h>
#include<errno.h>
#include<string.h>
#defineERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while(0)
intmain(int argc, char *argv[])
{
int fd;
fd = open("test2.txt",O_CREAT | O_RDWR | O_TRUNC, 0644);
if (fd == -1)
ERR_EXIT("openerror");
struct flock lock;
memset(&lock, 0, sizeof(lock));
lock.l_type = F_WRLCK;
lock.l_whence = SEEK_SET;
lock.l_start = 0;
lock.l_len = 0;
/*if (fcntl(fd, F_SETLK, &lock) ==0)*/
if (fcntl(fd, F_SETLKW, &lock) ==0)
{
printf("locksuccess\n");
printf("press any key tounlock\n");
getchar();
lock.l_type = F_UNLCK;
if (fcntl(fd, F_SETLK,&lock) == 0)
printf("unlocksuccess\n");
else
ERR_EXIT("unlockfail");
}
else
ERR_EXIT("lockfail");
return 0;
}
转载地址:http://dahkb.baihongyu.com/