文件系统简单的文件系统读写操作是使用uv_fs*函数和uv_fs_t结构完成的。注意:libuv文件系统操作不同于套接字操作。套接字操作使用操作系统提供的非阻塞操作。文件系统操作在内部使用阻塞函数,但这些函数在线程池中调用,并且在需要应用程序交互时通知注册到事件循环的观察者。所有文件系统函数都有两种形式——同步和异步。如果回调为null,则自动调用(并阻止)同步表单。该函数的返回值是一个libuv错误代码。这通常只对同步调用有用。当传递回调且返回值为0时,将调用异步表单。读/写文件打开文件描述符可以使用intuv_fs_open(uv_loop_t*loop,uv_fs_t*req,constchar*path,intflags,intmode,uv_fs_cbcb)标志和模式是标准的Unix标志。libuv负责转换为适当的Windows标志。您可以使用intuv_fs_close(uv_loop_t*loop,uv_fs_t*req,uv_filefile,uv_fs_cbcb)关闭文件描述符。文件系统操作回调有如下特点:voidcallback(uv_fs_t*req)让我们看一个cat的简单实现。我们首先注册一个用于文件打开的回调函数:uvcat/main.c-打开一个文件voidon_open(uv_fs_t*req){//传递给回调的请求与调用设置函数传递的请求相同。断言(请求==&open_req);if(req->result>=0){iov=uv_buf_init(buffer,sizeof(buffer));uv_fs_read(uv_default_loop(),&read_req,req->result,&iov,1,-1,on_read);}else{fprintf(stderr,"打开文件时出错:%s\n",uv_strerror((int)req->result));}}uv_fs_t的结果字段是uv_fs_open回调符号时的文件描述。如果文件打开成功,我们就开始读取文件。uvcat/main.c-读取回调voidon_read(uv_fs_t*req){if(req->result<0){fprintf(stderr,"Readerror:%s\n",uv_strerror(req->result));}elseif(req->result==0){uv_fs_tclose_req;//同步uv_fs_close(uv_default_loop(),&close_req,open_req.result,NULL);}elseif(req->result>0){iov.len=req->result;uv_fs_write(uv_default_loop(),&write_req,1,&iov,1,-1,on_write);在读取调用的情况下,您应该在触发读取回调之前传递一个已初始化并填充数据的缓冲区。uv_fs_*操作几乎直接映射到某些POSIX函数,因此EOF通常用result=0表示。在流或管道下,UV_EOF通常作为状态传递。在这里您可以看到编写异步程序时的常见模式。调用uv_fs_close()是同步执行的。通常任务是一次性执行的,或者作为启动或关闭阶段的一部分同步执行,当程序执行其主要任务并处理多个I/O源时,我们对快速I/O最感兴趣。对于单个任务,性能差异通常可以忽略不计,并且可能会导致代码更清晰。使用uv_fs_write()写入文件系统也很简单。您的回调将在写入完成后触发。在我们的例子中,回调只是驱动下一次读取。因此,读写过程都是通过回调来紧密执行的。uvcat/main.c-写入回调voidon_write(uv_fs_t*req){if(req->result<0){fprintf(stderr,"Writeerror:%s\n",uv_strerror((int)req->result));}else{uv_fs_read(uv_default_loop(),&read_req,open_req.result,&iov,1,-1,on_read);}}警告:由于文件系统和磁盘驱动程序的性能配置,一次写入成功可能不会提交到磁盘。我们在主函数中尝试再次读写uvcat/main.cintmain(intargc,char**argv){uv_fs_open(uv_default_loop(),&open_req,argv[1],O_RDONLY,0,on_open);uv_run(uv_default_loop(),UV_RUN_DEFAULT);uv_fs_req_cleanup(&open_req);uv_fs_req_cleanup(&read_req);uv_fs_req_cleanup(&write_req);return0;}警告:当文件系统请求释放libuv中的内部内存时,必须调用uv_fs_req_cleanup()函数。文件系统操作所有标准的文件系统操作(例如unlink、rmdir、stat)都是异步的,并且具有直观的参数顺序。它们遵循与读/写/打开调用相同的模式,返回uv_fs_t中的结果字段。完整列表如下:文件系统操作列表intuv_fs_close(uv_loop_t*loop,uv_fs_t*req,uv_filefile,uv_fs_cbcb);intuv_fs_open(uv_loop_t*loop,uv_fs_t*req,constchar*path,intflags,uv_fs_t*req,uv_filefile,uv_fs_cbcb));intuv_fs_read(uv_loop_t*loop,uv_fs_t*req,uv_filefile,constuv_buf_tbufs[],unsignedintnbufs,int64_toffset,uv_fs_cbcb);intuv_fs_unlink(uv_loop_t*loop,uv_fs_t*req,constchar*path,uv_fs_cbcb);intuv_fs_write(uv_loop_t*loop,uv_fs_t*req,uv_filefile,constuv_buf_tbufs[],unsignedintnbufs,int64_toffset,uv_fs_cbcb);intuv_fs_copyfile(uv_loop_t*loop,uv_fs_t*req,constchar*path,constchar*new_path,intflags,uv_fs_cbcb);intuv_fs_mkdir(uv_loop_t*loop,uv_fs_t*req,constchar*路径,intmode,uv_fs_cbcb);intuv_fs_mkdtemp(uv_loop_t*loop,uv_fs_t*req,constchar*tpl,uv_fs_cbcb);intuv_fs_rmdir(uv_loop_t*loop,uv_fs_t*req,constchar*path,uv_fs_cbcb);intuv_fs_scandir(uv_loop_t*loop,uv_fs_t*req,constchar*path,int标志,uv_fs_cbcb);intuv_fs_scandir_next(uv_fs_t*req,uv_dirent_t*ent);intuv_fs_opendir(uv_loop_t*loop,uv_fs_t*req,constchar*path,uv_fs_cbcb);intuv_fs_readdir(uv_loop_t*loop,uv_fs_dir_req_req_*dir,uv_fs_cbcb);intuv_fs_closedir(uv_loop_t*loop,uv_fs_t*req,uv_dir_t*dir,uv_fs_cbcb);intuv_fs_stat(uv_loop_t*loop,uv_fs_t*req,constchar*path,uv_fs_cb);intuv_fs_fstat(uv_loop_t*loop,uv_fs_t*req,uv_filefile,uv_fs_cbcb);intuv_fs_rename(uv_loop_t*loop,uv_fs_t*req,constchar*path,constchar*new_path,uv_fs_cbcb);intuv_fs_fsync(uv_loop_t*loop,uv_fs_t*req,uv_file文件,uv_fs_cbcb);intuv_fs_fdatasync(uv_loop_t*循环,uv_fs_t*req,uv_file文件,uv_fs_cbcb);intuv_fs_ftruncate(uv_loop_t*循环,uv_fs_t*req,uv_file文件,int64_t偏移量,uv_fs_cbcb);int_uv_uv_file(fs_loopsen*loop,uv_fs_t*req,uv_fileout_fd,uv_filein_fd,int64_tin_offset,size_tlength,uv_fs_cbcb);intuv_fs_access(uv_loop_t*loop,uv_fs_t*req,constchar*path,intmode,uv_fs_cbcb);intuv_fs_chmod(uv_loop_t*loop,uv_fs_t*req,constchar*path,intmode,uv_fs_cbcb);intuv_fs_utime(uv_loop_t*循环,uv_fs_t*req,constchar*path,doubleatime,doublemtime,uv_fs_cbcb);intuv_fs_futime(uv_loop_t*loop,uv_fs_t*req,uv_filefile,doubleatime,doublemtime,uv_fs_cbcb);intuv_fs_lstat(uv_loop_t*loop,uv_fs_t*req,constchar*path,uv_fs_cbcb);intuv_fs_link(uv_loop_t*loop,uv_fs_t*req,constchar*path,constchar*new_path,uv_fs_cbcb);intuv_fs_symlink(uv_loop_t*loop,uv_fs_t*req,constchar*路径,constchar*new_path,intflags,uv_fs_cbcb);intuv_fs_readlink(uv_loop_t*loop,uv_fs_t*req,constchar*path,uv_fs_cbcb);intuv_fs_realpath(uv_loop_t*loop,uv_fs_t*req,constchar*路径,uv_fs_cbcb);intuv_fs_fchmod(uv_loop_t*loop,uv_fs_t*req,uv_filefile,intmode,uv_fs_cbcb);intuv_fs_chown(uv_loop_t*loop,uv_fs_t*req,constchar*path,uv_uid_tuid,uv_gid_tgid,uv_fs_cbcb);intuv_fs_lchown(uv_loop_t*循环,uv_fs_t*req,uv_file文件,uv_uid_tuid,uv_gid_tgid,uv_fs_cbcb);intuv_fs_lchown(uv_loop_t*循环*req,uv_fs_const图表路径,uv_uid_tuid,uv_gid_tgid,uv_fs_cbcb);buffersandstreamslibuv中基本的I/O句柄是streams(uv_stream_t)TCP套接字,UDP套接字,文件I/O的管道,IPC都是Stream的子类。流使用每个子类的自定义函数进行初始化,然后在使用uv_buf_tbufs[],unsignedintnbufs,uv_write_cbcb)时进行操作;基于流的函数比文件系统函数更易于使用。当uv_read_start()被调用一次,libuv会自动从流中读取数据,直到uv_read_stop()被调用transfer。不连续的数据单元是缓冲区-uv_buf_t。
