2024年android emulator虚拟设备之qemu pipe分析(三),2024年最新移动端开发工程师面试题

结尾

我还总结出了互联网公司Android程序员面试涉及到的绝大部分面试题及答案,并整理做成了文档,以及系统的进阶学习视频资料分享给大家。
(包括Java在Android开发中应用、APP框架知识体系、高级UI、全方位性能调优,NDK开发,音视频技术,人工智能技术,跨平台技术等技术资料),希望能帮助到你面试前的复习,且找到一个好的工作,也节省大家在网上搜索资料的时间来学习。

image

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

r = platform_get_resource(pdev, IORESOURCE_IRQ, 0);

if (r == NULL) {

printk(KERN_ERR “QEMU PIPE Device: failure to allocate IRQ\n”);

err = -EINVAL;

goto err_alloc_irq;

}

dev->irq = r->start;

PIPE_D(“The IRQ is %d\n”, dev->irq);

err = request_irq(dev->irq, qemu_pipe_interrupt, IRQF_SHARED,

“goldfish_pipe”, dev);

if (err)

goto err_alloc_irq;

spin_lock_init(&dev->lock);

err = misc_register(&qemu_pipe_device);

if (err)

goto err_misc_register;

setup_access_params_addr(dev);

return 0;

err_misc_register:

free_irq(dev->irq, pdev);

err_alloc_irq:

iounmap(dev->base);

dev->base = NULL;

return err;

}

qemu_pipe_open,每次打开/dev/qemu_pipe都会alloc一个新的qemu_pipe结构体,每个qemu_pipe结构体对应一个CHANNEL,qemu_pipe结构体将被添加到一个radix_tree中。将qemu_pipe的地址作为CHANNEL(不可能重复的)写入PIPE_REG_CHANNEL寄存器,然后写CMD_OPEN到PIPE_REG_COMMAND中,去打开新的CHANNEL。最后设置了filp的私有变量为qemu_pipe结构体。

static int qemu_pipe_open(struct inode *inode, struct file *file)

{

unsigned long irq_flags;

struct qemu_pipe *pipe;

struct qemu_pipe_dev *dev = pipe_dev;

int32_t status;

int ret;

/* Allocate new pipe kernel object */

pipe = kzalloc(sizeof(*pipe), GFP_KERNEL);

if (pipe == NULL) {

PIPE_E(“Not enough kernel memory to allocate new pipe\n”);

return -ENOMEM;

}

PIPE_D(“Opening pipe %p\n”, pipe);

pipe->dev = dev;

mutex_init(&pipe->lock);

init_waitqueue_head(&pipe->wake_queue);

/* Now, tell the emulator we’re opening a new pipe. We use the

* pipe object’s address as the channel identifier for simplicity.

*/

spin_lock_irqsave(&dev->lock, irq_flags);

if ((ret = radix_tree_insert(&dev->pipes, (unsigned long)pipe, pipe))) {

spin_unlock_irqrestore(&dev->lock, irq_flags);

PIPE_E(“opening pipe failed due to radix tree insertion failure\n”);

kfree(pipe);

return ret;

}

writel((unsigned long)pipe, dev->base + PIPE_REG_CHANNEL);

writel(CMD_OPEN, dev->base + PIPE_REG_COMMAND);

status = readl(dev->base + PIPE_REG_STATUS);

spin_unlock_irqrestore(&dev->lock, irq_flags);

if (status < 0) {

PIPE_E(“Could not open pipe channel, error=%d\n”, status);

kfree(pipe);

return status;

}

/* All is done, save the pipe into the file’s private data field */

file->private_data = pipe;

return 0;

}

qemu_pipe_read和qemu_pipe_write都是使用qemu_pipe_read_write来实现的,注意access_ok和__get_user/__put_user对于用户空间指针的检测。具体的读写比较简单,就是操作IO寄存器而已,需要注意的是,如果是非阻塞方式,需要进行阻塞等待。

具体的方法就是往PIPE_REG_COMMAND里面写CMD_WAKE_ON_WRITE或者CMD_WAKE_ON_READ,然后调用wait_event_interruptible去等待!test_bit(wakeBit, &pipe->flags)。

当中断来临时,会检查每一个CHANNEL的PIPE_REG_WAKES寄存器,如果可读 or 可写 or 已关闭,中断函数中会清除pipe->flags中的对应的等待标志位,然后wait_event_interruptible等待结束。如果是qemu_pipe被关闭的情况,wait_event_interruptible等待结束之后,检查到错误状态并退出。

/* This function is used for both reading from and writing to a given

* pipe.

*/

static ssize_t qemu_pipe_read_write(struct file *filp, char __user *buffer,

size_t bufflen, int is_write)

{

unsigned long irq_flags;

struct qemu_pipe *pipe = filp->private_data;

struct qemu_pipe_dev *dev = pipe->dev;

const int cmd_offset = is_write ? 0
(CMD_READ_BUFFER - CMD_WRITE_BUFFER);

unsigned long address, address_end;

int ret = 0;

/* If the emulator already closed the pipe, no need to go further */

if (test_bit(BIT_CLOSED_ON_HOST, &pipe->flags)) {

PIPE_W(“(write=%d) already closed!\n”, is_write);

ret = -EIO;

goto out;

}

/* Null reads or writes succeeds */

if (unlikely(bufflen) == 0)

goto out;

/* Check the buffer range for access */

if (!access_ok(is_write ? VERIFY_WRITE : VERIFY_READ,

buffer, bufflen)) {

ret = -EFAULT;

PIPE_W(“rw access_ok failed\n”);

goto out;

}

/* Serialize access to the pipe *

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值