文件I/O(二)
(6)lseek
lseek和標準I/O庫的fseek函數類似,可以移動當前讀寫位置(或者叫偏移量)
#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);
參數:
fd 表示要操作的文件描述符
offset是相對於whence(基準)的偏移量
whence 可以是SEEK_SET(文件指針開始),SEEK_CUR(文件指針當前位置) ,SEEK_END為文件指針尾
返回值:文件讀寫指針距文件開頭的字節大小,出錯,返回-1
lseek 主要作用是移動文件讀寫指針,因此還有以下兩個作用
1.拓展文件,不過一定要一次寫的操作。迅雷等下載工具在下載文件時候先擴展一個空間,然後再下載的。
#include<sys/stat.h> #include<fcntl.h> #include<unistd.h> #include<errno.h> #include<stdlib.h> int main() { int fd=open("abc",O_RDWR); if(fd<0) { perror("open abc"); exit(-1); }//擴展一個文件,一定要有一次寫操作 lseek(fd,ox1000,SEEK_SET); write(fd,“a”,1); close(fd); return 0; }
註:看一個文件裏邊的內容 od -tcx 文件名
2.獲取文件大小
利用返回值:文件讀寫指針距文件開頭的字節大小,出錯,返回-1
fd=open("hello",O_RDWR); if(fd<0) { perror("open hello"); exit(-1); } printf("hello size=%d\n",lseek(fd,0,SEEK_END));
close(fd);
3.移動讀寫指針的位置
(7)fcntl
獲取或設置文件的訪問控制屬性
功能描述:根據文件描述詞來操作文件的特性。
#include <unistd.h>
#include <fcntl.h>
int fcntl(int fd, int cmd);
int fcntl(int fd, int cmd, long arg);
int fcntl(int fd, int cmd, struct flock *lock);
fcntl()針對(文件)描述符提供控制。參數fd是被參數cmd操作(如下面的描述)的描述符。針對cmd的值,fcntl能夠接受第三個參數int arg。
[返回值]
fcntl()的返回值與命令有關。如果出錯,所有命令都返回-1,如果成功則返回某個其他值。下列三個命令有特定返回值:F_DUPFD , F_GETFD , F_GETFL以及F_GETOWN。
F_DUPFD 返回新的文件描述符
F_GETFD 返回相應標誌
F_GETFL , F_GETOWN 返回一個正的進程ID或負的進程組ID
F_SETFD
fcntl函數有5種功能:
1. 復制一個現有的描述符(cmd=F_DUPFD).
2. 獲得/設置文件描述符標記(cmd=F_GETFD或F_SETFD).
3. 獲得/設置文件狀態標記(cmd=F_GETFL或F_SETFL).
4. 獲得/設置異步I/O所有權(cmd=F_GETOWN或F_SETOWN).
5. 獲得/設置記錄鎖(cmd=F_GETLK , F_SETLK或F_SETLKW).
#include <unistd.h> #include <fcntl.h> #include <errno.h> #include <string.h> #include <stdlib.h> #define MSG_TRY "try again\n" int main(void) { char buf[10]; int n; int flags; flags = fcntl(STDIN_FILENO, F_GETFL);//獲取一個文件的訪問控制屬性 flags |= O_NONBLOCK; if (fcntl(STDIN_FILENO, F_SETFL, flags) == -1)//設置 { perror("fcntl"); exit(1); } tryagain: n = read(STDIN_FILENO, buf, 10); if (n < 0) { if (errno == EAGAIN) { sleep(1); write(STDOUT_FILENO, MSG_TRY,strlen(MSG_TRY)); goto tryagain; } perror("read stdin"); exit(1); } write(STDOUT_FILENO, buf, n); return 0; }
fcntl
(8)ioctl
ioctl用於向設備發控制和配置命令大部分驅動,除了需要具備讀寫設備的能力之外,還需要具備對硬件控制的能力。
#include<sys/ioctl.h> int ioctl(int d,int request,...);
其中d就是用戶程序打開設備時使用open函數返回的文件描述符,request就是用戶程序對設備的控制命令,至於後面的省略號,則是一些補充參數,一般最多一個,有或沒有是和request的意義相關的,詳情請參考man 2 ioctl_list以了解更多。ioctl函數是文件結構中的一個屬性分量,就是說如果驅動程序提供了對ioctl的支持,用戶就可以在用戶程序中使用ioctl函數控制設備的I/O通道或其它一些自己想要控制且設備支持的功能。
fcntl 共性,ioctl個性
#include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<sys/ioctl.h> int main(void) { struct winsize size;//winsize指定終端文件的大小 if(isatty(STDOUT_FILENO==0)//判斷是否為終端文件,大於0是,==0不是 exit(1); if(ioctl(STDOUT_FILENO,TIOCGWINSZ,&size)<0)//獲取終端窗口大小存入到size { perror("ioctl TIOCGWINSZ error"); exit(1); } printf(%d rows,%d columns\n",size.ws_row,size.ws_col); return 0; }
在圖形界面的終端裏多次改變終端窗口大小並運行該程序,觀察結果。
文件I/O(二)