APUE学习(二)IO

1.中规定了文件标识符:

//头文件多在/usr/include/下

* Standard file descriptors.  */
#define	STDIN_FILENO	0	/* Standard input.  */
#define	STDOUT_FILENO	1	/* Standard output.  */
#define	STDERR_FILENO	2	/* Standard error output.  */

2.open

#include

int open( const char* path, int flags);
int open( const char* path, int flags, mode_t mode);
int openat( int fd, const char* path, int flags);
int openat( int fd, const char* path, int flags, mode_t mode);

flags:

    a.O_RDONLY, O_WROLNY, O_RDWR,O_SEARCH,O_EXEC,五个中必须而且只能选择一个

    b.下面是可选的:

        O_APPEND:写追加,必须是O_WRONLY或者O_RDWR时使用

        O_CREAT:若不存在则创建.必须使用mode,实际mode是8进制数与umask的与

        O_EXCL:必须Q_CREAT | Q_EXCL使用,如果已存在会报错

        O_DIRECTORY:目录

        O_ NOFOLLOW:不是符号连接

        O _NOBLOCK:若文件是FIFO,块,字,则非阻塞

        O_TRUNC:文件写打开时,截断为0

        O_SYNS:等待write等物理操作完成

        O_DSYNC:同O_SYNC,但写不影响读时,无需等待

        O_RSYNC  read 等待所有写入同一区域的写操作完成后再进行

open()或openat()打开的是未用的最小fd,

例子:

#include
#include
#include

int main( int argc, char*argv[])
{
//open
int fd;
const char *fileName= "tempfile";
int flags_open=O_WRONLY|O_CREAT|O_EXCL;
mode_t mode_open= 0644;
fd= open(fileName,flags_open,mode_open);
if(- 1==fd)
{
perror( "open error");
return - 1;
}
else
{
printf( "fd: %d open \n ",fd);
        close(fd);
}
return 0;
}

sun@sun-PC:~/Downloads/linux/UNIX环境高级编程.tar/apue.3e/fileio$ gcc opentest.c
sun@sun-PC:~/Downloads/linux/UNIX环境高级编程.tar/apue.3e/fileio$ ./a.out
fd: 3 open
sun@sun-PC:~/Downloads/linux/UNIX环境高级编程.tar/apue.3e/fileio$ ./a.out
open error: File exists    

3.creat()

#include

int creat( const char* name, mode_t mode);
==> int open(name,O_WRONLY|O_CREAT|O_TRUNC,mode);

4.close()

#include

int close( int fd);

当一个进程结束,内核会自动close所有文件

5.lseek()

#include
#include

int lseek( int fd, off_t offset, int whence);

whence                            offset

SEEK_SET                        非负,开始处偏移

SEEK_CUR                      正负零,当前位置偏移

SEEK_END                        正负零,末尾偏移

例子:

#include "apue.h"
#include


char    buf1[] = "abcdefghij";
char    buf2[] = "ABCDEFGHIJ";

int
main( void)
{
     int     fd;

     if ((fd = creat( "file.hole", FILE_MODE)) < 0)
         err_sys( "creat error");

     if ( write(fd, buf1, 10) != 10)
         err_sys( "buf1 write error");
     /* offset now = 10 */

     if ( lseek(fd, 16384, SEEK_SET) == - 1)
         err_sys( "lseek error");
     /* offset now = 16384 */

     if ( write(fd, buf2, 10) != 10)
         err_sys( "buf2 write error");
     /* offset now = 16394 */

     exit( 0);
}

6.read

/*
#include
ssize_t read(int fd, void *buf, size_t count);
参数:从fd里最多读count个字节到buf
返回值:读到:返回实际读取字节
读到最后:返回0
错误:返回-1

*/
#include
#include
#include
#include
#include
#include
#include

int main( void)
{
int fd;
ssize_t size;
char buf[ 1024];
fd= open( "readtest.c",O_RDONLY);
if(fd==- 1)
{
perror( "open error");
exit( 1);
}
do{
bzero(buf, 1024);
size= read(fd,buf, 1024);
if(size==- 1)
{
perror( "read error");
exit( 1);
}
printf( "%s",buf);
} while(size> 0);
exit( 0);

}

7.write

/*
#include

ssize_t write(int fd, const void *buf, size_t count);
返回值与count相同成功,不然出错

*/
#include
#include
#include
#include
#include
#include


int main( int argc, char const *argv[])
{
int fd;
ssize_t size;
char buf[]= "Hello World! \n ";
fd= open( "tmp.txt",O_WRONLY|O_CREAT|O_APPEND, 0666);
if(fd==- 1)
{
perror( "open error");
exit( 1);
}
size= write(fd,buf, sizeof(buf));
if(size!= sizeof(buf))
{
perror( "write error");
exit( 1);
}
return 0;
}

8.IO效率

read(),write()的buf长度和磁盘块长度相同最佳,ext文件系统为4096

9.文件共享

不同进程操作同一个文件,文件描述符可能不同,分别有一个文件表项,文件表项由文件偏移量和v节点(i节点)组成,不同进程的文件偏移量不同,但是v节点相同,节点信息(包括所有者,打开方式,文件长度等)相同.

10.原子操作

1.追加到一个文件

    原子操作是一个函数完成的,不能调用另外一个函数,因为随时可能挂起

    open()时使用O_APPEND是原子操作,而lseek(fd,0,SEEK_END)后写不是原子操作

2.函数pread和pwrite
       #include 

       ssize_t pread(int fd, void *buf, size_t count, off_t offset);

       ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset);

先lseek再读写,并且保证原子性

3.创建文件

open(fd,O_WRONLY|O_CREAT|O_EXCL)是原子的

11.dup和dup2

/*
#include

int dup(int oldfd);
int dup2(int oldfd, int newfd);

#define _GNU_SOURCE
#include
#include

int dup3(int oldfd, int newfd, int flags);
*/
#include
#include
#include
#include
#include
#include


int main( int argc, char const *argv[])
{
int fd,flags,ret;
if(argc!= 3)
{
printf( "argc !=3 \n ");
_exit( 1);
}
if( strcmp(argv[ 1], "y")!= 0 && strcmp(argv[ 1], "yy")!= 0)
{
printf( "argv[1] != > or >> \n ");
_exit( 1);
}
if( strcmp(argv[ 1], "yy")!= 0)
{
flags=O_RDWR|O_CREAT|O_TRUNC;
}
else
{
flags=O_RDWR|O_CREAT|O_APPEND;
}
fd= open(argv[ 2],flags,S_IRUSR|S_IWUSR);
if(fd==- 1)
{
perror( "open error");
_exit( 1);
}
ret= dup2(fd,STDOUT_FILENO); //argv[2]的文件描述符为1了
if(ret==- 1)
{
perror( "dup2 error");
_exit( 1);
}
close(fd); //这个文件描述符用不到了
printf( "STDOUT \n ");
fflush(stdout);
close(STDOUT_FILENO);
return 0;
}

12.sync,fsync.fdatasync

       #include 
       void sync(void);

       int fsync(int fd);

       int fdatasync(int fd);

sync:将缓冲区排入队列

fsync:等待向fd写操作完成才返回

fdatasync:只关注fd的数据部分更新完成

13.fcntl


你可能感兴趣的:(linux)