1. 程式人生 > >文件I/O(二)

文件I/O(二)

ring goto 配置命令 個性 printf 異步 div 進程組id 結構

(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(二)