簡體   English   中英

UIO 和 msync:為什么即使地址是 PAGESIZE 的倍數,msync 也會返回“無效參數”

[英]UIO and msync: Why does msync return "invalid argument" even though the address is a multiple of PAGESIZE

Linux 版本:4.19
平台:Xilinx Ultrascale+ Zynq

在可編程邏輯中,我創建了一個位於物理地址 0xA0001000 的內存映射設備。 我使用 uio_pdrv_genirq 作為我的設備驅動程序。 該設備顯示為 uio0,我已准備好使用 mmap 對其進行讀寫。 我希望能夠保證我所做的任何寫入都會立即寫入設備,而不是等待 Linux 自行刷新臟頁。 為此,我應該根據我所有的研究使用 msync。 但是當我這樣做時,我不斷收到錯誤消息。 這是我的測試程序:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>

void main() {
    int fid;
    int rval;
    char *data;
    int idx;

    printf("Open UIO Device \n");
    fid= open("/dev/uio0", O_RDWR | O_SYNC);

    data= mmap(NULL, 0x1000, PROT_WRITE|PROT_READ, MAP_SHARED, fid, 0);
    if(MAP_FAILED == data) {
        printf("Error code when mapping! %s", strerror(errno));
    }
    printf("addr= 0x%8X\n", data);
    printf("pagesize= 0x%4X\n", getpagesize());

    printf("Write some data\n");
    data[11]= 0xDE;
    data[10]= 0xC0;
    data[ 9]= 0xDE;
    data[ 8]= 0xAD;

    rval= msync(data, 0x1000, MS_SYNC);
    if(-1 == rval) {
        printf("Error on msync! %s\n", strerror(errno));
    }

    if(munmap(data, 0x1000) < 0) {
        printf("munmap error! %s\n", strerror(errno));
    }

    printf("Close UIO device\n");
    rval= close(fid);
    if(rval != 0) {
        printf("UIO device close Error!\n");
    }
}

這是程序輸出:

mylinux:~/test-apps$ ./a.out
Open UIO Device
addr= 0xABA05000
pagesize= 0x1000
Write some data
Error on msync! Invalid argument
Close UIO device

我不明白這個錯誤的來源。 msync 手冊頁指出,如果地址不是 PAGESIZE 的倍數,則會發生此錯誤。 但是正如您從上面的示例中看到的那樣,它是一個倍數。 甚至物理地址也是 PAGESIZE 的倍數。

其他一些注意事項:

  1. 即使我從標志中刪除 O_SYNC 到 open 函數,我也會遇到同樣的錯誤。
  2. 進入 FPGA 架構的 AXI4 總線是 128 位,然后由 Xilinx IP 模塊轉換為 32 位。 我不認為這與我的問題有任何關系。

感謝人們提供的任何見解。

我相信EINVAL錯誤是因為內核的msync系統調用處理程序(在“ mm/msync.c ”中)調用vfs_fsync_range

            error = vfs_fsync_range(file, fstart, fend, 1);

並且vfs_fsync_range (在“ fs/sync.c ”中)在此處返回-EINVAL

    if (!file->f_op->fsync)
        return -EINVAL;

因為 UIO 驅動核心(在“ drivers/uio/uio.c ”中沒有設置fsync文件操作處理程序。


您擁有mmap ed 的物理內存在頁表中映射為非緩存內存,因此不需要刷新寫入。 但是,您可能應該使用對內存映射 I/O 寄存器的volatile訪問。 內核中的readbwriteb等寄存器訪問函數是特定於體系結構的,但總是將地址轉換為指向volatile整數類型的指針(例如volatile unsigned char *volatile unsigned short *volatile unsigned int *取決於訪問內存位置之前的寄存器訪問寬度)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM