您的位置:首页 > 运维架构 > Linux

标准库I/O vs linux api I/O全面比较 系列2-------POSIX通用异步库AIO(1)

2013-10-30 14:57 537 查看
 比较基础的部分 我就不表示了 比如怎么用aio_read(),aio_write()  aio_erro() aio_return() 具体可以man aio_read (你懂的)

下面我们主要是来分析这个AIO库在做一个通用程序时 到底做了什么动作,这些动作到底给你所带来的系统有什么好处?

也只是做一个比较肤浅的分析:

先帖一个简单的代码:【也不知道怎么弄代码片段 直接复制吧】

  1 #include <stdio.h>

  2 #include <aio.h>

  3 #include <fcntl.h>

  4 #include <string.h>

  5 #include <errno.h>

  6 #define BUFFSIZE 1024

  7 int main()

  8 {

  9          int fd;

 10          int ret;

 11          struct aiocb test_aio;

 12          if((fd=open("test.txt",O_RDONLY))==-1)printf("open wrong");

 13          memset(&test_aio,0,sizeof(struct aiocb));

 14          test_aio.aio_buf=malloc(sizeof(char)*BUFFSIZE);

 15          test_aio.aio_fildes=fd;

 16          test_aio.aio_nbytes=BUFFSIZE;

 17          test_aio.aio_offset=0;

 18          if((ret=aio_read(&test_aio))<0)

 19                  printf("wrong aio_read");

 20         //这种是一直在等待中 让其一直在忙等待中

 21         while(aio_error(&test_aio)==EINPROGRESS);

 22         if((ret=aio_return(&test_aio))>0)

 23         {

 24 

 25                 printf("异步读取数据已经成功!\n");

 26                 printf("%s",test_aio.aio_buf);

 27         }

 28         else

 29                 printf("异步读取数据失败!");

 30 

 31 }

可以看到这个其实是一个很简单的数据读取到内存中来。我们用strace -f ./a.out 做一个查询,看下系统在接受这个可执行程序之后都做了什么动作:

toms@toms-Vostro-260s:~/C_C++_TEST$ strace -f ./a.out 

execve("./a.out", ["./a.out"], [/* 47 vars */]) = 0

brk(0)                                  = 0x9e3e000

access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)

mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb779b000

access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)

open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3

fstat64(3, {st_mode=S_IFREG|0644, st_size=100835, ...}) = 0

mmap2(NULL, 100835, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7782000

close(3)                                = 0

access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
open("/lib/i386-linux-gnu/librt.so.1", O_RDONLY|O_CLOEXEC) = 3  -------------------------------------- (1)

read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0p\31\0\0004\0\0\0"..., 512) = 512-----------------(2)


fstat64(3, {st_mode=S_IFREG|0644, st_size=30696, ...}) = 0

mmap2(NULL, 33352, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb7779000

mmap2(0xb7780000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x6) = 0xb7780000

close(3)                                = 0

access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)

open("/lib/i386-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3

read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\220\232\1\0004\0\0\0"..., 512) = 512

fstat64(3, {st_mode=S_IFREG|0755, st_size=1770984, ...}) = 0

mmap2(NULL, 1780508, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb75c6000

mmap2(0xb7773000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1ad) = 0xb7773000

mmap2(0xb7776000, 11036, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb7776000

close(3)                                = 0

access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)

open("/lib/i386-linux-gnu/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 3

read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\320[\0\0004\0\0\0"..., 512) = 512

fstat64(3, {st_mode=S_IFREG|0755, st_size=124637, ...}) = 0

mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb75c5000

mmap2(NULL, 107008, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb75aa000

mmap2(0xb75c1000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x16) = 0xb75c1000

mmap2(0xb75c3000, 4608, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb75c3000

close(3)                                = 0

mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb75a9000

set_thread_area({entry_number:-1 -> 6, base_addr:0xb75a96c0, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0

mprotect(0xb7773000, 8192, PROT_READ)   = 0

mprotect(0xb75c1000, 4096, PROT_READ)   = 0

mprotect(0xb7780000, 4096, PROT_READ)   = 0

mprotect(0x8049000, 4096, PROT_READ)    = 0

mprotect(0xb77be000, 4096, PROT_READ)   = 0

munmap(0xb7782000, 100835)              = 0

set_tid_address(0xb75a9728)             = 3811

set_robust_list(0xb75a9730, 0xc)        = 0

futex(0xbfaf3604, FUTEX_WAIT_BITSET_PRIVATE|FUTEX_CLOCK_REALTIME, 1, NULL, b75a96c0) = -1 EAGAIN (Resource temporarily unavailable)

rt_sigaction(SIGRTMIN, {0xb75af5f0, [], SA_SIGINFO}, NULL, 8) = 0

rt_sigaction(SIGRT_1, {0xb75af680, [], SA_RESTART|SA_SIGINFO}, NULL, 8) = 0

rt_sigprocmask(SIG_UNBLOCK, [RTMIN RT_1], NULL, 8) = 0

getrlimit(RLIMIT_STACK, {rlim_cur=8192*1024, rlim_max=RLIM_INFINITY}) = 0

uname({sys="Linux", node="toms-Vostro-260s", ...}) = 0

open("test.txt", O_RDONLY)              = 3

brk(0)                                  = 0x9e3e000

brk(0x9e5f000)                          = 0x9e5f000

sched_getparam(3811, { 0 })             = 0

sched_getscheduler(3811)                = 0 (SCHED_OTHER)

rt_sigprocmask(SIG_SETMASK, ~[RTMIN RT_1], [], 8) = 0

mmap2(NULL, 27520, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0) = 0xb7794000

mprotect(0xb7794000, 4096, PROT_NONE)   = 0
clone(Process 3812 attached-----------------------------------------------------------------------------------------(3)

child_stack=0xb7799fe4, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0xb779a728, {entry_number:6, base_addr:0xb779a6c0, limit:1048575, seg_32bit:1, contents:0,
read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}, child_tidptr=0xb779a728) = 3812

[pid  3811] rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0

[pid  3812] set_robust_list(0xb779a730, 0xc) = 0

[pid  3812] pread64(3, "hello \347\254\254\344\270\200\344\270\252linux aio\347\250\213\345\272\217\357\274"..., 1024, 0) = 34    -------------------------------------------------------------------------------------(4)

[pid  3812] getuid32( <unfinished ...>

[pid  3811] fstat64(1,  <u
ac93
nfinished ...>

[pid  3812] <... getuid32 resumed> )    = 1000

[pid  3811] <... fstat64 resumed> {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0

[pid  3812] rt_sigqueueinfo(3811, SIG_0, {} <unfinished ...>

[pid  3811] mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0 <unfinished ...>

[pid  3812] <... rt_sigqueueinfo resumed> ) = 0

[pid  3811] <... mmap2 resumed> )       = 0xb7793000

[pid  3812] gettimeofday( <unfinished ...>

[pid  3811] write(1, "\345\274\202\346\255\245\350\257\273\345\217\226\346\225\260\346\215\256\345\267\262\347\273\217\346\210\220\345\212\237\357\274"..., 34异步读取数据已经成功!

 <unfinished ...>

[pid  3812] <... gettimeofday resumed> {1383114881, 327461}, NULL) = 0

[pid  3811] <... write resumed> )       = 34

[pid  3812] clock_gettime(CLOCK_REALTIME,  <unfinished ...>

[pid  3811] write(1, "hello \347\254\254\344\270\200\344\270\252linux aio\347\250\213\345\272\217\357\274"..., 34hello 第一个linux aio程序!

 <unfinished ...>

[pid  3812] <... clock_gettime resumed> {1383114881, 327594745}) = 0

[pid  3811] <... write resumed> )       = 34

[pid  3812] futex(0xb77811a4, FUTEX_WAIT_PRIVATE, 1, {0, 999866255} <unfinished ...>

[pid  3811] exit_group(34)              = ?

这是一个完整的过程哦 ,可能东西比较多 一步步的来看下:

首先可以看出来 这个pid 有2个进程号 pid 3812 和3811 不往深入分析 本身他就调用了linux本身的创建进程,看过LINUX内核的人应该知道:这里的 (3)调用的是clone.   这个动作就是由aio_read()函数触发的!!

Linux的轻量级进程---就是线程。也就是其本身而言,就是调用Clone一个进程来执行读文件操作,自身进程继续执行,我们在来看上面的调用 ;3182是子进程 3181是父进程。为什么要分析这个呢 ?这个其实对后面的分析aio_read到底做了什么动作是非常重要的。

对于3182而言 :我们执行了(4)也就是我们本身而言,子进程就是异步的一个模拟,同步模拟异步。pread()这个函数是一个阻塞函数哦,pread()本身而言,可能会导致3182的一个阻塞,阻塞完成了I/O 必须通过信号量机制传递。这个信号量在后面有提示的。后面的过程我觉得就比较简单了

也就是说 AIO本身而言 是自己创建线程 用同步来模拟异步哦 表示这样的思路可以用pthread库写一个来模拟异步的传输,下一篇我们就把上面那个代码用pthread线程机制来模拟的代码传上来。

当然本身而言 AIO应该在很多方面做了优化 我仅仅是分析出这个AIO的一个大体的执行流程,然后对以后的分析性能是有帮助的!! 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  AIO IO模型 异步