linux系統中的IO操作
阻塞IO:
一直阻塞程序直到完成IO操作。
非阻塞IO:
有資料時進行IO操作,沒有資料時立即返回不阻塞程序。
訊號驅動IO:
當有資料到來是傳送訊號給程序執行IO操作,提高CPU的利用率。當設定開啟檔案描述字O_ASYNC標誌是可以用於訊號驅動的IO操作,也可以用過fcntl()改變檔案標籤,當檔案進行IO操作時會產生SIGIO訊號或套接字有帶外資料到來時會產生SIGURG訊號。通過fcntl函式執行F_SETOWN命令可以設定/獲得,接收訊號的程序/程序組ID。
具體例項:
/* * main.c * * Created on: 2016年10月22日 * Author: chy */ #include <sys/types.h> #include <sys/stat.h> #include <sys/unistd.h> #include <termios.h> #include <signal.h> #include <sys/fcntl.h> #include <sys/fcntl.h> #include <stdio.h> #include <stdlib.h> FILE *file; void sigfunc(int sig) { char c,input[128]; int n; static int i = 0; if(read(STDIN_FILENO,&c,1) > 0){ if(c != '\n') input[i++] = c; else { input[i++] = '\0'; fprintf(file,"NO sig=%d, input line is %s\n",i,input); i = 0; if(c == 'q'){ fclose(file); _exit(0); } } } } int main(int argc,char *argv) { int falg; char buff[256]; struct termios newseting,old_termios; file = fopen("test.txt","w"); signal(SIGIO,sigfunc); tcgetattr(STDIN_FILENO,&old_termios); newseting = old_termios; newseting.c_iflag &= (~ICANON); newseting.c_cc[VTIME] = 0; newseting.c_cc[VMIN] = 1; tcsetattr(STDIN_FILENO, TCSANOW, &newseting); fcntl(STDIN_FILENO, F_SETOWN,getpid()); falg = fcntl(STDIN_FILENO, F_GETFL,0); falg |= O_ASYNC; fcntl(STDIN_FILENO,F_SETFL,falg); while(1) sleep(1); return 0; }
多路轉接IO:
處理來自多個通道的輸入,通過select函式告訴呼叫它的程序需要等待IO事件的數量。
#include <sys/select.h> #include <sys/time.h> int select(int nfds,fd_set *rfds,fd_set *wfds,fd_set *edfs,struct timeval *timeout); void FD_ZERO(fd_set *fdset); //初始化描述字為空 void FD_CLR(int filedes,fd_set *fdset); //將filedes描述字從fdset描述字集合中清除 int FD_ISSET(int fileds,fd_set *fdset); //判斷filedes是否屬於fdset所指的描述 void FD_SET(int filedes,fd_set *fdset); //將filedes新增到描述字fset所指的集合中 select中的三個測試描述字集合都為空可以做為定時器切精度高於sleep。
非同步IO:能夠在較短時間內從多個接收通道收集大量的資料,非同步IO操作在IO期間不阻塞發出IO請求的程序,其IO操作由作業系統派生新的執行緒並行的執行,當IO操作結束是傳送訊號給傳送請求IO操作的程序通知其IO操作完成,程序也可以呼叫aio_suspend阻塞程序等待IO操作完成。
具體例項:#include <aio.h> int aio_write(struct aiocb *aiocbp);//返回實際寫入的位元組數 int aio_read(struct aiocb *aiocbp); //返回實際讀出的位元組數 int lio_listio(int mode,struct aiocb *restrict const list[restrict],int nent,struct sigevent *restrict notification); int aio_error(struct aiocb *aiocbp); //正在進行IO操作返回EINPROGRESS ssize_t aio_return(struct aiocb *aiocbp); //返回讀寫位元組個數 int aio_suspend(const struct aiocb *const list[],int nent,const struct timespec *timeout); //掛起呼叫程序直到IO完成或時間到期 int aio_sysnc(int op,struct aiocb *aiocbp); //把資料同步到物理磁碟 struct aiocb{ int aio_filds; off_t aio_offset; volatile void *aio_buf; size_t aio_nbytes; int aio_reqprio; struct sigevent aio_sigevent; int aio_lio_opcode; }; struct sigevent{ union sigval sigev_value; int sigv_signo; int sigev_notify;//非同步事件的通知型別 SIGEV_NONE(不通知)、SIGEV_SIGNAL(生成訊號)、SIGEV_THREAD(執行sigev_notify_function指定的函式) void (*sigev_notify_function) (union sigval); pthread_attr_t *sigev_notify_attrbutes; };
/*
* main.c
*
* Created on: 2016年10月20日
* Author: chy
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/fcntl.h>
#include <sys/unistd.h>
#include <aio.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#define buffer_num 2
#define buffer_size 2048
#define ERR(msg,f_num) { \
if(f_num < 0) { \
fprintf(stderr,"%s",msg); \
exit(-1); \
} \
}
typedef enum{
buffer_ferr = 1,
buffer_full,
buffer_write
}BUFFER;
typedef struct { //緩衝區結構
BUFFER state;
int fillpt;
char buffer[buffer_size];
struct aiocb aio;
}buffer_t;
static buffer_t buffer[buffer_num];
static sigset_t procmask;
static int write_num = 0;
static int sig_num;
static volatile off_t seek_ptr;
void sig_func(int signo,siginfo_t *info,void *sig)
{
int i;
buffer_t *temp;
if(info->si_signo != SIGRTMIN || info->si_code != SI_ASYNCIO)
return;
else
printf("write over\n");
temp = (buffer_t*)info->si_value.sival_ptr;
int write_temp_num = 0;
if(aio_error(&temp->aio) != EINPROGRESS)
write_temp_num = aio_return(&temp->aio);
write_num += write_temp_num;
sig_num++;
temp->fillpt = 0;
temp->state = buffer_ferr;
return;
}
buffer_t *find_empty_buffer()
{
int i;
sigset_t newsig;
sigprocmask(SIG_BLOCK,&procmask,&newsig); //遮蔽非同步寫訊號量
while(1){
for(i = 0; i < buffer_num; i++)
if(buffer[i].state == buffer_ferr)
break;
if(i == buffer_num)
sigsuspend(&procmask); //掛起SIGRTMIN
else break;
}
buffer[i].state = buffer_full;
buffer[i].fillpt = 0;
sigprocmask(SIG_SETMASK,&procmask,NULL); //恢復遮蔽非同步寫訊號量
return (&buffer[i]);
}
void buffer_flush(buffer_t *temp)
{
temp->aio.aio_offset = seek_ptr; //檔案指標的位置
seek_ptr += temp->fillpt;
temp->aio.aio_buf = temp->buffer; //緩衝地地址
temp->aio.aio_nbytes = temp->fillpt; //要傳輸的位元組數
temp->aio.aio_reqprio = 0; //優先移位0
temp->aio.aio_sigevent.sigev_notify = SIGEV_SIGNAL; //實時訊號型別
temp->aio.aio_sigevent.sigev_signo = SIGRTMIN; //訊號數
temp->aio.aio_sigevent.sigev_value.sival_ptr = temp; //攜帶的資訊
temp->state = buffer_write; //標記為正在寫的狀態
ERR("write fail\n",aio_write(&temp->aio));
return;
}
int main(int argc,char *argv[])
{
int i,file_in,file_out;
struct sigaction sig;
buffer_t *buffer_opt;
if(argc < 3){
printf("please input three func\n");
exit(0);
}
file_in = open(argv[1],O_RDONLY);
ERR("open file_in faile\n",file_in);
file_out = open(argv[2],O_WRONLY | O_CREAT,0777);
ERR("open file_out faile\n",file_out);
for(i = 0; i < buffer_num; i++){
buffer[i].state = buffer_ferr;
buffer[i].fillpt = 0;
buffer[i].aio.aio_fildes = file_out; //繫結檔案描述字
}
buffer_opt = find_empty_buffer();
sigemptyset(&procmask);
sigaddset(&procmask,SIGRTMIN);
sigemptyset(&sig.sa_mask);
sig.sa_flags = SA_SIGINFO;
sig.sa_sigaction = sig_func;
ERR("sigaction fail\n",sigaction(SIGRTMIN,&sig,NULL));
int read_num;
while(1){
while((read_num = read(file_in,buffer_opt->buffer + buffer_opt->fillpt,buffer_size)) != 0){
if(read_num > 0){
buffer_opt->fillpt += read_num;
if(buffer_opt->fillpt == buffer_size){
buffer_flush(buffer_opt);
buffer_opt = find_empty_buffer();
break;
}
}
if(errno == EINTR)
break;
else if(read_num < 0 && errno != EINTR)
ERR("read faile\n",-1);
}
if(read_num == 0){
printf("chen\n");
buffer_flush(buffer_opt);
break;
}
}
for(i = 0; i < buffer_num; i++)
if(buffer[i].state == buffer_write){
struct aiocb *temp[1];
temp[0] = &buffer[i].aio;
aio_suspend(temp, 1, NULL);
}
close(file_out);
close(file_in);
printf("this is over\n");
return 1;
}
儲存對映IO:傳統IO進行讀寫檔案要進行多次系統呼叫,並且把檔案載入到自己的地址空間,其效率低,浪費儲存空間。儲存對映IO,系統把檔案的一頁讀取到記憶體,每一個程序把改頁對映到自己的記憶體空間。對映後不再需要read等系統呼叫,可以通過指令直接訪問。儲存對映分為共享對映和私有對映,共享對映每個程序都能夠改變對映頁的內容,當一頁被重新整理時保回會物理磁碟。私有對映,寫檔案將導致複製該頁的一個副本,物理磁碟物件本身不改變。
#include <sys/mman.h>
void *mmap(void *addr,size_t len,int port,int flags,int filedes,off_t off);
int munmap(void *paddr,size_t len); //刪除對映
int msync(void *addr,size_t len,int flags); //寫入到物理磁碟
addr:對映區在記憶體的起始地址。
len:對映的位元組數。
prot:對映區的保護許可權。
flags:對映區的屬性。
filedes: 已開啟檔案的描述字。
off:檔案要對映的其實位元組位置。
相關推薦
Linux系統程式設計---IO操作
1.系統呼叫 系統呼叫效率較低 1.系統呼叫開銷大,要從使用者空間切換到核心空間,然後切換回使用者空間 2.系統呼叫與底層驅動相關,不一定能夠按指定一次寫完。write函式 #include <unistd> size_t write(int files,
linux系統中的IO操作
同步IO分為阻塞IO、非阻塞IO、訊號驅動的IO和多路轉接IO。阻塞IO: 一直阻塞程序直到完成IO操作。 非阻塞IO: 有資料時進行IO操作,沒有資料時立即返回不阻塞程序。 訊號驅動IO: 當有資料到來是傳送訊號給程序執行IO操作,提高CPU的利用率。當設定開啟檔案描述字
Linux系統中安裝MySQL數據庫操作手冊
linux mysql數據庫 Linux系統中MySQL數據庫安裝手冊一、安裝概述: 在Linux操作系統中安裝MySQL數據庫是一個我們必須要掌握的一門技術,也決定了你以後找工作的薪資待遇,所以你知道它的厲害了吧!學會安裝只是第一步,你還得學好數據庫的基本操作,以及搭建一個數據庫的主從配置等等
Linux系統中MySQL的常用操作命令
char OS var 權限 記錄 port nis whereis null 服務: # chkconfig --list 列出所有系統服務# chkconfig --list | grep on 列出所有啟動的系統服務 # chkconfig -
Linux系統中vim的常用操作
######### vim ########## 1.##vim模式## *)命令模式 用vim開啟一個檔案就進入這個模式了(這是vim預設的模式),在這個模式中可以輸入相關命令 *)插入模式 進入vim中按小寫的i鍵進入vim的插入模式 *)退出模式 按Esc鍵按
linux系統中設定oracle啟停服務操作步驟
現在很多資料庫伺服器都是安裝的linux系統,比如說,oracle資料庫,安裝完以後,不會隨著linux系統啟動。那麼可以寫一個指令碼,來實現這個功能。 1 配置監聽 安裝完oracle以後,可以配置下監聽服務,這樣方便使用者遠端連線。在下面這兩個路徑下 /opt/orac
在linux系統中跟蹤高IO等待
原文作者:Jon Buys 跟蹤大型分散式系統的效能問題,從本質上來講是複雜的。應用為什麼慢?瓶頸在哪裡?以我的經驗,最主要的罪魁禍首之一是高IO等待(即high IO wait)。換一個地方用的話來說:每個人都只是在等待[翻譯參考文獻1]。 高IO
linux系統中python的模組 || python的檔案操作
一.模組:itchat微信登陸 1.模組:在 Python 中,一個.py檔案就稱之為一個模組(Module)。 •大大提高了程式碼的可維護性; •編寫程式碼不必從零開始。當一個模組編寫完畢,就可以被其 他地方引用; 2.包:如果不同的人編寫的模組名相同怎
Cgroup限制CPU、IO、記憶體以及linux系統中的排程策略
一、CPU 1、0核利用 思路: 0核是必須要保護的,否則各種系統命令、喂狗都可能出問題; &
老男孩教育每日一題-2017年5月12日-磁盤知識點:linux系統中LVM配置實現方法?
邏輯卷管理 磁盤 每日一題 1.題目老男孩教育每日一題-2017年5月12日-磁盤知識點:linux系統中LVM配置實現方法?2.參考答案01:將一個或多個物理分區創建為一個PV# pvcreate /dev/sdb{1,2} Physical volume "/dev/sdb1" success
linux系統中定時任務
linu tab 一次 腳本 lin edi 路徑 執行 表示 1、查看所有定時任務:命令:“crontab -l” 數字意思解釋如下:從左到右,依次是:分、時、日、月、星期。 2、編輯定時執行計劃:命令:"crontab -e" ,e表示edit修改的意思。 3、修
Linux 系統中這樣修復 SambaCry 漏洞
windows 服務器 解決方案 linux 非官方 導讀Samba 很久以來一直是為 linux 系統上的 Windows 客戶端提供共享文件和打印服務的標準。家庭用戶,中型企業和大型公司都在使用它,它作為最佳解決方案在多種操作系統共存的環境中脫穎而出,由於廣泛使用的工具很可能發生這種情
linux 系統中的 /bin /sbin /usr/bin /usr/sbin /usr/local/bin /usr/local/sbin 目錄的區別
。。 process pre this 用戶 unix table mount sent 先來段英文的: /bin This directory contains executable programs which are needed in single user
Linux 系統中安裝Mysql_5.6
上傳 粘貼 啟動mysql grant ont linu chm cli char Linux 系統中安裝Mysql_5.6 安裝包下載地址(http://pan.baidu.com/s/1o8G5q
在Linux系統中安裝vmTools
cdr cdrom linu 是否 壓縮 進入 span pan tin 以下是,會用到的命令、遇到的問題及解釋: 在虛擬機中安裝centOS系統,因為後續安裝服務或者其他的東西,因此需要安裝vmTools,方便將文件從宿主電腦拖進虛擬機內。(我的是tar壓縮包的vmToo
Linux系統中有關/dev/null和/dev/zero文件說明及實踐
linux /dev/null 特殊文件 /dev/zero Linux系統中有關/dev/null和/dev/zero文件說明提示:這個題目完全可以作為一個面試題考考運維的應聘者:面試題:請解釋Linux中/dev/null和/dev/zero兩個文件的作用和區別。在類Unix操作系統中,
運維學習之Linux系統中的文件傳輸、歸檔、壓縮
linux不同系統之間的文件傳輸1.文件歸檔1.文件歸檔,就是把多個文件變成一個歸檔文件2.tar c ##創建 f ##指定歸檔文件名稱 t ##顯示歸檔文件中的內容 r ##向歸檔文件中添加文件 --get ##取出單個文件 --delete ##刪除單個文件 x ##取出歸檔文件中的所有內容
Linux系統中如何查看日誌信息
日誌文件 系統日誌 楊書凡 日誌文件是用於記錄Linux系統中各種運行消息的文件,不同的日誌文件記載了不同類型的信息,對於診斷和解決系統中的問題很有幫助分析日誌文件 日誌數據主要包括三種類型:內核及系統日誌、用戶日誌、程序日誌 #對於大多數的文本格式的日誌文件,使用tail、more、l
Linux系統中修改/etc/profile文件的方法
linux在Linux系統中etc/profile文件一般是不能更改的,想要更改etc/profile文件就要用一些特殊的技巧進行Linux文件修改。本文就來介紹一下Linux系統中修改/etc/profile文件的方法:etc/profile文件是只讀的,直接用vi或gedit打開修改後是無法保存的。要修改
Linux系統中svn服務器設置開機啟動
數據庫 檢查 reat version 打開端口 rest grep 建立 標簽 安裝完svn服務器後雖然好用但是因為經常重啟Linux服務器,每次重啟完就要去手動啟動svn服務器,很是麻煩,於是在網上找了一些方法後,自己把svn服務器設置成開機啟動 步驟一:安裝svn服務