一、read系統調用
一旦有了與一個打開文件描述相關連的文件描述符,只要該文件是用O_RDONLY或O_RDWR標誌打開的,就可以用read()系統調用從該文件中讀取字節
函數原型:
ssize_t read(int fd, void *buf, size_t count);
參數:
fd :想要讀的文件的文件描述符
buf : 指向內存塊的指針,從文件中讀取來的字節放到這個內存塊中
count : 從該文件複製到buf中的字節個數
返回值:
如果出現錯誤,返回-1;讀文件結束,返回0;否則返回從該文件複製到規定的緩衝區中的字節數
二、write系統調用
用write()系統調用將數據寫到一個文件中
函數原型:
ssize_t write(int fd, const void *buf, size_t count);
函數參數:
fd:要寫入的文件的文件描述符
buf: 指向內存塊的指針,從這個內存塊中讀取數據寫入 到文件中
count: 要寫入文件的字節個數
返回值:如果出現錯誤,返回-1;如果寫入成功,則返回寫入到文件中的字節個數
三、ioctl 函數
ioctl用於向設備發控制和配置命令,有些命令也需要讀寫一些數據,但這些數據是不能用read/write讀寫的,稱爲Out-of-band數據。也就是說,read/write讀寫的數據是in-band數據,是I/O操作的主體,而ioctl命令傳送的是控制信息,其中的數據是輔助的數據。例如,在串口線上收發數據通過read/write操作,而串口的波特率、校驗位、停止位通過ioctl設置,A/D轉換的結果通過read讀取,而A/D轉換的精度和工作頻率通過ioctl設置。
#include <sys/ioctl.h>
int ioctl(int d, int request, ...);
d是某個設備的文件描述符。request是ioctl的命令,可變參數取決於request,通常是一個指向變量或結構體的指針。若出錯則返回-1,若成功則返回其他值,返回值也是取決於request。
以下程序使用TIOCGWINSZ命令獲得終端設備的窗口大小。
#include <stdio.h>
#include <stdlib.h
#include <unistd.h>
#include <sys/ioctl.h
int main(void)
{
struct winsize size;
if (isatty(STDOUT_FILENO) == 0)
exit(1);
if(ioctl(STDOUT_FILENO, TIOCGWINSZ, &size) < 0)
{
perror("ioctl TIOCGWINSZ error");
exit(1);
}
printf("%d rows, %d columns\n", size.ws_row, size.ws_col);
return 0;
}
四、文件的隨機讀寫
到目前爲止的所有文件訪問都是順序訪問。這是因爲所有的讀和寫都從當前文件的偏移位置開始,然後文件偏移值自動地增加到剛好超出讀或寫結束時的位置,使它爲下一次訪問作好準備。
有個文件偏移這樣的機制,在Linux系統中,隨機訪問就變得很簡單,你所需做的只是將當前文件偏移值改變到有關的位置,它將迫使下一次read()或write()發生在這一位置。(除非文件打開時標誌有 O_APPEND,在這種情況下,任何write調用仍將發生在文件結束處)
lseek系統調用:
功能說明:通過指定相對於開始位置、當前位置或末尾位置的字節數來重定位,這取決於 lseek() 函數中指定的位置
函數原型:off_t lseek (int fd, off_t offset, int base);
函數參數:
fd:需要設置的文件描述符
offset:偏移量
base:偏移基位置
返回值:返回新的文件偏移值
base 表示搜索的起始位置,有以下幾個值:(這些值定義在<unistd.h>)
base 文件位置
SEEK_SET 從文件開始處計算偏移
SEEK_CUR 從當前文件的偏移值計算偏移
SEEK_END 從文件的結束處計算偏移
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<fcntl.h>
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#define ERR_EXIT(m) \
do { \
perror(m); \
exit(EXIT_FAILURE); \
} while(0)
int main(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 src error");
if ((outfd = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0664)) == -1)
ERR_EXIT("open dest error");
char buf[1024];
ssize_t nread;
while ((nread = read(infd, buf, 1024)) > 0)
write(outfd, buf, nread); // 可以調用fsync同步內核緩衝區的數據到磁盤文件
// 或者打開文件時標誌爲O_SYNC
close(infd);
close(outfd);
/********************************************************************************************/
infd = open("test.txt", O_RDONLY);
if (infd == -1)
ERR_EXIT("open error");
char buf2[1024] = {0};
int num = read(infd, buf2, 5);
if (num == -1)
ERR_EXIT("read error");
num = lseek(infd, 0, SEEK_CUR); // 從當前位置偏移0個字節
if (num == -1)
ERR_EXIT("lseek");
printf("current offset=%d\n", num);
outfd = open("dest.txt", O_WRONLY | O_CREAT | O_TRUNC, 0664);
if (outfd == -1)
ERR_EXIT("open error");
write(outfd,buf2, 5);
close(infd);
close(outfd);
return 0;
}
在struct
stat結構體中的文件長度對應st_size字段,而文件使用的塊大小對應st_blksize字段,佔用塊數對應st_blocks字段。 大部分情況下面,st_size和st_blksize*st_blocks應該是很接近的,除非一種情況就是文件空洞。
一般對應於空洞文件來說,st_size可能很大,而實際佔用磁盤空間卻很少。