Golang 异步(bsd/linux)io

2024-03-21 02:20
文章标签 linux golang 异步 io bsd

本文主要是介绍Golang 异步(bsd/linux)io,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Golang 异步(bsd/linux)io

在日常开发中,读写文件的底层调用函数是syscall.Read/Write。一切都是围绕这两个函数展开的,不过有时候需要或者就是单纯想异步执行。liburing是linux上一个很好的原生异步io库,这里需要适配bsd派系的系统,所以选择的是另一款libaio,这款异步io库在bsd派系(macos,freebsd,openbsd…)和linux上都是存在的。
golang 类unix系统下 os.OpenFile函数的底层(windows就不要来找茬了:-(
请添加图片描述
写入文件的底层:syscall.Write是系统写入函数,ignoringEINTRIO函数会回调传入的syscall.Write函数
请添加图片描述

package main
//由于golang系统调用中没有定义aio需要用到的关键结构体aiocb,所以我们需要借助cgo来使其生成一份golang的aiocb结构体
/*
#include <aio.h>
*/
import "C"
import ("fmt""log""syscall""time""unsafe"
)type File struct {fd int
}
type AIOCB C.struct_aiocbfunc OpenFile(pathname string, mode, perm int) (*File, error) {fd, err := syscall.Open(pathname, mode, uint32(perm))if err != nil {return nil, err}//bsd派系系统走此函数设定绕过内核和用户层缓冲区,linux系统直接上方mode加入O_DIRECT即可syscall.Syscall(syscall.SYS_FCNTL, uintptr(fd), syscall.F_NOCACHE, 0)var f = File{fd: fd}return &f, nil
}
func (f *File) Write(b []byte) *AIOCB {var aiocb AIOCBaiocb.aio_buf = unsafe.Pointer(&b[0])blen := len(b)aiocb.aio_nbytes = C.size_t(blen)aiocb.aio_fildes = C.int(f.fd)syscall.Syscall(syscall.SYS_AIO_WRITE, uintptr(unsafe.Pointer(&aiocb)), 0, 0)return &aiocb
}
func (f *File) Close() error {return syscall.Close(f.fd)
}
func (f *File) Read(b []byte) *AIOCB {var aiocbp AIOCBaiocbp.aio_buf = unsafe.Pointer(&b[0])aiocbp.aio_nbytes = C.size_t(len(b))aiocbp.aio_fildes = C.int(f.fd)syscall.Syscall(syscall.SYS_AIO_READ, uintptr(unsafe.Pointer(&aiocbp)), 0, 0)return &aiocbp
}
//由于异步操作会立即返回,所以刚刚操作返回的aiocb结构体的指针非常关键,千万不要丢了,如果需要知道写入或读出操作有没有完成,需要通过aio_return这个函数来感知,如果操作未完成会返回-1
func Verify(a *AIOCB) int {ans, _, _ := syscall.Syscall(syscall.SYS_AIO_RETURN, uintptr(unsafe.Pointer(a)), 0, 0)return int(int32(ans))
}

由于异步操作会立即返回,所以刚刚操作返回的aiocb结构体的指针非常关键,千万不要丢了,如果需要知道写入或读出操作有没有完成,需要通过aio_return这个函数来感知,如果操作未完成会返回-1

测试代码

func main() {f, err := OpenFile("test.txt", syscall.O_CREAT|syscall.O_RDONLY, 0644)if err != nil {log.Fatalln(err)}defer f.Close()var b []byte = make([]byte, 128)status := f.Read(b)fmt.Println(Verify(status))time.Sleep(time.Second)fmt.Println(Verify(status))
}

这篇关于Golang 异步(bsd/linux)io的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/831492

相关文章

Linux之systemV共享内存方式

《Linux之systemV共享内存方式》:本文主要介绍Linux之systemV共享内存方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、工作原理二、系统调用接口1、申请共享内存(一)key的获取(二)共享内存的申请2、将共享内存段连接到进程地址空间3、将

快速修复一个Panic的Linux内核的技巧

《快速修复一个Panic的Linux内核的技巧》Linux系统中运行了不当的mkinitcpio操作导致内核文件不能正常工作,重启的时候,内核启动中止于Panic状态,该怎么解决这个问题呢?下面我们就... 感谢China编程(www.chinasem.cn)网友 鸢一雨音 的投稿写这篇文章是有原因的。为了配置完

Golang HashMap实现原理解析

《GolangHashMap实现原理解析》HashMap是一种基于哈希表实现的键值对存储结构,它通过哈希函数将键映射到数组的索引位置,支持高效的插入、查找和删除操作,:本文主要介绍GolangH... 目录HashMap是一种基于哈希表实现的键值对存储结构,它通过哈希函数将键映射到数组的索引位置,支持

Redis消息队列实现异步秒杀功能

《Redis消息队列实现异步秒杀功能》在高并发场景下,为了提高秒杀业务的性能,可将部分工作交给Redis处理,并通过异步方式执行,Redis提供了多种数据结构来实现消息队列,总结三种,本文详细介绍Re... 目录1 Redis消息队列1.1 List 结构1.2 Pub/Sub 模式1.3 Stream 结

Linux命令之firewalld的用法

《Linux命令之firewalld的用法》:本文主要介绍Linux命令之firewalld的用法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux命令之firewalld1、程序包2、启动firewalld3、配置文件4、firewalld规则定义的九大

Linux之计划任务和调度命令at/cron详解

《Linux之计划任务和调度命令at/cron详解》:本文主要介绍Linux之计划任务和调度命令at/cron的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux计划任务和调度命令at/cron一、计划任务二、命令{at}介绍三、命令语法及功能 :at

Linux下如何使用C++获取硬件信息

《Linux下如何使用C++获取硬件信息》这篇文章主要为大家详细介绍了如何使用C++实现获取CPU,主板,磁盘,BIOS信息等硬件信息,文中的示例代码讲解详细,感兴趣的小伙伴可以了解下... 目录方法获取CPU信息:读取"/proc/cpuinfo"文件获取磁盘信息:读取"/proc/diskstats"文

使用Python实现一个优雅的异步定时器

《使用Python实现一个优雅的异步定时器》在Python中实现定时器功能是一个常见需求,尤其是在需要周期性执行任务的场景下,本文给大家介绍了基于asyncio和threading模块,可扩展的异步定... 目录需求背景代码1. 单例事件循环的实现2. 事件循环的运行与关闭3. 定时器核心逻辑4. 启动与停

Linux内核参数配置与验证详细指南

《Linux内核参数配置与验证详细指南》在Linux系统运维和性能优化中,内核参数(sysctl)的配置至关重要,本文主要来聊聊如何配置与验证这些Linux内核参数,希望对大家有一定的帮助... 目录1. 引言2. 内核参数的作用3. 如何设置内核参数3.1 临时设置(重启失效)3.2 永久设置(重启仍生效

C#中async await异步关键字用法和异步的底层原理全解析

《C#中asyncawait异步关键字用法和异步的底层原理全解析》:本文主要介绍C#中asyncawait异步关键字用法和异步的底层原理全解析,本文给大家介绍的非常详细,对大家的学习或工作具有一... 目录C#异步编程一、异步编程基础二、异步方法的工作原理三、代码示例四、编译后的底层实现五、总结C#异步编程