Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux 如何验证原子写入?_Linux_Embedded_Arm_Atomic_Rs485 - Fatal编程技术网

Linux 如何验证原子写入?

Linux 如何验证原子写入?,linux,embedded,arm,atomic,rs485,Linux,Embedded,Arm,Atomic,Rs485,我一直在孜孜不倦地(在S[O | F | U]网络和其他地方)搜索,并认为这是一个不同寻常的问题。我正在使用运行Debian Linux 2.6.28-4的Atmel AT91SAM9263-EK开发板(ARM926EJ-S内核,ARMv5指令集)。我正在使用(我相信)tty驱动程序与一个用户对话。我需要确保写入和读取是原子的。有几行源代码(在本文末尾相对于内核源代码安装目录列出)暗示或隐式地说明了这一点 是否有任何方法可以验证向该设备写入/读取数据实际上是一种原子操作?或者,是否将/dev/t

我一直在孜孜不倦地(在S[O | F | U]网络和其他地方)搜索,并认为这是一个不同寻常的问题。我正在使用运行Debian Linux 2.6.28-4的Atmel AT91SAM9263-EK开发板(ARM926EJ-S内核,ARMv5指令集)。我正在使用(我相信)tty驱动程序与一个用户对话。我需要确保写入和读取是原子的。有几行源代码(在本文末尾相对于内核源代码安装目录列出)暗示或隐式地说明了这一点

是否有任何方法可以验证向该设备写入/读取数据实际上是一种原子操作?或者,是否将/dev/ttyXX设备视为FIFO,并且参数到此结束?仅仅相信代码是在强制执行它所提出的这一主张似乎是不够的——就在今年2月freebsd被执行的时候。是的,我意识到freebsd与Linux并不完全相同,但我的观点是,仔细确定一下并没有什么坏处。我所能想到的就是不断地发送数据,寻找一种排列方式——我希望有一种更科学、更理想、更确定的方式。不幸的是,我完全不记得我在大学时代的并行编程课程。如果能给我一记耳光或是朝正确的方向一推,我将不胜感激。如果您选择回复,请提前感谢

亲切问候,

房祖名


drivers/char/tty_io.c:1087

void tty_write_message(struct tty_struct *tty, char *msg)
{
    lock_kernel();
    if (tty) {
        mutex_lock(&tty->atomic_write_lock);
        if (tty->ops->write && !test_bit(TTY_CLOSING, &tty->flags))
            tty->ops->write(tty, msg, strlen(msg));
        tty_write_unlock(tty);
    }
    unlock_kernel();
    return;
}

拱/臂/包括/asm/bitops.h:37

static inline void ____atomic_set_bit(unsigned int bit, volatile unsigned long *p)
{
    unsigned long flags;
    unsigned long mask = 1UL << (bit & 31);

    p += bit >> 5;

    raw_local_irq_save(flags);
    *p |= mask;
    raw_local_irq_restore(flags);
}
static inline void\uuuuuuuuuuu原子集\u位(无符号整数位,易失性无符号长*p)
{
无符号长旗;
无符号长掩码=1UL>5;
原始本地irq保存(标志);
*p |=面罩;
原始本地irq恢复(标志);
}

驱动程序/串行/串行_核心.c:2376

static int
uart_write(struct tty_struct *tty, const unsigned char *buf, int count)
{
    struct uart_state *state = tty->driver_data;
    struct uart_port *port;
    struct circ_buf *circ;
    unsigned long flags;
    int c, ret = 0;

    /*
     * This means you called this function _after_ the port was
     * closed.  No cookie for you.
     */
    if (!state || !state->info) {
        WARN_ON(1);
        return -EL3HLT;
    }

    port = state->port;
    circ = &state->info->xmit;

    if (!circ->buf)
        return 0;

    spin_lock_irqsave(&port->lock, flags);
    while (1) {
        c = CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE);
        if (count < c)
            c = count;
        if (c <= 0)
            break;
        memcpy(circ->buf + circ->head, buf, c);
        circ->head = (circ->head + c) & (UART_XMIT_SIZE - 1);
        buf += c;
        count -= c;
        ret += c;
    }
    spin_unlock_irqrestore(&port->lock, flags);

    uart_start(tty);
    return ret;
}
static int
uart_写入(结构tty_结构*tty,常量无符号字符*buf,整数计数)
{
结构uart_state*state=tty->driver_data;
结构uart_端口*端口;
结构周期*周期;
无符号长旗;
int c,ret=0;
/*
*这意味着您在端口被调用后调用了此函数
*关门了,没有饼干给你。
*/
如果(!state | |!state->info){
警告(1);
返回-EL3HLT;
}
端口=状态->端口;
circ=&state->info->xmit;
如果(!circ->buf)
返回0;
自旋锁定irqsave(&port->lock,flags);
而(1){
c=循环空间到循环结束(循环->头部,循环->尾部,UART\u XMIT\u大小);
如果(计数head,buf,c);
circ->head=(circ->head+c)和(UART\u XMIT\u SIZE-1);
buf+=c;
计数-=c;
ret+=c;
}
旋转\u解锁\u irqrestore(&port->lock,flags);
uart_启动(tty);
返回ret;
}
此外,从man write(3)文档中:

尝试写入管道或FIFO有几个主要特征:

  • 原子/非原子:如果在一个操作中写入的全部数据没有与来自任何其他进程的数据交错,则写入是原子的。当有多个写入程序向单个读卡器发送数据时,这非常有用。应用程序需要知道以原子方式执行的写入请求的大小。这个最大值称为{PIPE_BUF}。IEEE Std 1003.1-2001的本卷并未说明超过{PIPE_BUF}字节的写入请求是否为原子请求,但要求{PIPE_BUF}或更少字节的写入应为原子请求

我认为,从技术上讲,设备不是先进先出(FIFO),所以根本不清楚您所引用的保证是否适用

您是否担心进程内的部分写入和读取,或者您实际上是在从不同进程读取和/或写入同一设备?假设是后者,您最好实现某种代理进程。代理独占设备并执行所有读写操作,因此完全避免了多进程原子性问题


简而言之,我建议不要试图验证“从这个设备读/写实际上是一个原子操作”。如果一个更高版本的linux(或完全不同的o/s)无法按照您需要的方式实现原子性,那么您将很难自信地做到这一点,并且应用程序将面临微妙的故障。

我认为
PIPE\u BUF
是正确的选择。现在,少于
PIPE\BUF
字节的写入可能不是原子性的,但如果不是原子性的,那就是操作系统的错误。我想你可以在这里问一个操作系统是否知道bug。但实际上,如果它有这样一个bug,它应该立即修复

如果你想写的不仅仅是原子化的管道,我认为你运气不好。我认为除了应用程序协调和合作之外,没有任何方法可以确保较大规模的写操作以原子方式进行


这个问题的一个解决方案是将您自己的进程放在设备前面,并确保希望写入设备的每个人都与该进程联系并将数据发送给它。然后,您可以在原子性保证方面做任何对您的应用程序有意义的事情。

如果您将“问题”放在顶部(排序摘要),您可能会得到更好的响应。我做了更改,谢谢您的提示-听起来你真正想要的是一个折磨司机的压力测试来验证正确性。这似乎在所有方面都非常有用。试图通过阅读源代码或对当前版本运行压力测试来推断API保证,这听起来像是一个错误。@Dale,谢谢你的回答。在回答您的问题时,只有一个读/写过程,但我需要确保读/写过程不会中断。也就是说,中断、抢占,所有可能干扰的操作都会在写操作或读操作期间暂停。我相信传输量非常小,16位或2 cl的几个因数