小编cos*_*us0的帖子

如何使用保留的CMA内存?

我想为具有DMA支持的设备分配一块物理连续的保留内存(在预定义的物理地址中)。如我所见,CMA具有三个选项:1.通过内核配置文件保留内存。2.通过内核cmdline保留内存。3.通过设备树内存节点保留内存。在第一种情况下:可以保留区域的大小和数量。

CONFIG_DMA_CMA=y
CONFIG_CMA_AREAS=7
CONFIG_CMA_SIZE_MBYTES=8
Run Code Online (Sandbox Code Playgroud)

所以我可以使用:

start_cma_virt = dma_alloc_coherent(dev->cmadev, (size_t)size_cma, &start_cma_dma, GFP_KERNEL);
Run Code Online (Sandbox Code Playgroud)

在我的驱动程序中分配连续的内存。我最多可以使用7次,最多可以分配8M。但遗憾的是

dma_contiguous_reserve(min(arm_dma_limit, arm_lowmem_limit));
Run Code Online (Sandbox Code Playgroud)

从arch / arm / mm / init.c:

void __init arm_memblock_init(struct meminfo *mi,const struct machine_desc *mdesc)
Run Code Online (Sandbox Code Playgroud)

不可能为连续分配设置预定义的物理地址。当然我可以使用内核cmdline:

mem=cma=cmadevlabel=8M@32M cma_map=mydevname=cmadevlabel
//struct device *dev = cmadev->dev; /*dev->name is mydevname*/
Run Code Online (Sandbox Code Playgroud)

之后,dma_alloc_coherent()应该在物理内存区域中从32M + 8M(0x2000000 + 0x800000)到0x27FFFFF分配内存。但不幸的是,我对此解决方案有疑问。也许我的cmdline有错误?下一个尝试是设备树实现。

cmadev_region: mycma {
    /*no-map;*/ /*DMA coherent memory*/
    /*reusable;*/
    reg = <0x02000000 0x00100000>;      
};
Run Code Online (Sandbox Code Playgroud)

并在某些节点中:

memory-region = <&cmadev_region>;
Run Code Online (Sandbox Code Playgroud)

正如我通常在内核中看到的那样,应将其使用为:

of_find_node_by_name(); //find needed node
of_parse_phandle(); //resolve a phandle property to a device_node pointer
of_get_address(); //get DT __be32 …
Run Code Online (Sandbox Code Playgroud)

memory-management virtual-memory linux-device-driver linux-kernel device-tree

6
推荐指数
1
解决办法
7469
查看次数

recvmsg返回EDEADLK?

我有套接字族PF_PACKET类型SOCK_RAW.通过recvmsg和poll()读取的消息.我随后和周期性地得到了recvmsg返回EDEADLK.我尝试用下一个代码调试这个问题.我尝试调查阻止我的套接字描述符的人和方式.可能有人知道其他方法怎么调试这种情况?正如我理解的那样

EDEADLK资源死锁避免了.试图锁定可能导致死锁情况的系统资源.在我的情况下,它是套接字文件描述符锁定问题.分配系统资源套接字文件描述符会导致死锁情况.系统不保证它会注意到所有这些情况.这个错误意味着你很幸运,系统注意到了.

error = recvmsg(fd, &msghdr, flags);
msghdr_flags = msg_hdr.msg_flags;

void recvmsg_errno(int fd, unsigned int msghdr_flags, int flags, int error)
{
    struct flock fl;
    memset(&fl, 0x0, sizeof(fl));

    printf("recvmsg return: %d errno: %d description: %s\n", error, errno,
                    strerror(errno));

    printf("recvmsg flags: %x %d\n", flags, flags);
    if (flags & MSG_ERRQUEUE) printf("MSG_ERRQUEUE\n");
    if (flags & MSG_OOB) printf("MSG_OOB\n");
    if (flags & MSG_PEEK) printf("MSG_PEEK\n");
    if (flags & MSG_TRUNC) printf("MSG_TRUNC\n");
    if (flags & MSG_WAITALL) printf("MSG_WAITALL\n");

    printf("msghdr flags: %x %d\n", msghdr_flags, msghdr_flags);
    if (msghdr_flags & MSG_EOR) printf("MSG_EOR\n");           //indicates …
Run Code Online (Sandbox Code Playgroud)

c sockets linux linux-kernel

3
推荐指数
1
解决办法
827
查看次数

内核导出符号vs全局符号vs静态全局?

我有点堆栈与内核符号类型的含义.简单的静态符号与C static具有相同的含义.因此局部静态变量具有局部范围和静态分配.静态函数作用域是一个文件.但静态导出符号呢?如何应对EXPORT_SYMBOL(),EXPORT_PER_CPU_SYMBOL(),EXPORT_UNUSED_SYMBOL()如果宏观出口静态符号?全局符号和导出符号有什么区别?链接器是否有责任为导出的符号添加其他信息?全局静态变量内置内核是否在所有内核和可加载模块中都可见?

可以从可加载模块访问内核导出的符号.内核中的这种符号是否很好用?当内核解析符号时,它是通过内核符号表进行查找的吗?

c linux linux-kernel

2
推荐指数
1
解决办法
850
查看次数