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


 比较基础的部分 我就不表示了 比如怎么用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,  <unfinished ...>
[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的一个大体的执行流程,然后对以后的分析性能是有帮助的!! 





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值