E / S Síncrona em arquivos sysfs

0

Gostaria de garantir que o que escrevo em um arquivo sysfs (especificamente os arquivos /sys/class/gpio ) seja sincronizado com o registro real. O código que eu inicialmente tinha aberto o arquivo com o O_SYNC flag, que eu assumi fez isso. No entanto, em outro trecho de código, tentei usar fsync() , mas ele falhou com EINVAL e man fsync me diz:

   EROFS, EINVAL
          fd is bound to a special file which does not support synchronization

Eu verifiquei o código para possíveis operações em um arquivo sysfs e não encontrei nenhum tipo de do_sync_write ou do_fsync funções.

Então, o O_SYNC flag tem algum efeito ao abrir um arquivo sysfs? Não deve open devolver um código de erro quando tenta abrir um ficheiro que não suporta a sincronização de leitura / escrita com O_SYNC ?

Atenciosamente,

Guilherme

    
por Guilherme Costa 01.04.2016 / 14:58

1 resposta

3

/ sys é um sistema de arquivos completamente baseado em RAM para acesso a estruturas de dados do kernel. Isso inclui as interfaces GPIO .

Tudo o que você precisa fazer é abrir o pseudofile normalmente e usar uma única gravação para gravar os dados. Se for bem sucedido, e todos os dados (exceto possivelmente qualquer espaço em branco como newlines) foram escritos, o kernel assegura que aceitou tudo. Em outras palavras:

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

#define GPIO_EXPORT_PATH "/sys/class/gpio/export"

static int gpio_export(int pin)
{
    char        buffer[32];
    ssize_t     written;
    int         fd;
    char *const q = buffer + sizeof buffer;
    char       *p = buffer + sizeof buffer;

    if (pin < 0)
        return errno = EINVAL;

    *(--p) = '\n';

    do {
        *(--p) = '0' + (pin % 10);
        pin /= 10;
    } while (pin > 0);

    do {
        fd = open(GPIO_EXPORT_PATH, O_WRONLY);
    } while (fd == -1 && errno == EINTR);
    if (fd == -1)
        return errno;

    do {
        written = write(fd, p, (size_t)(q - p));
    } while (written == -1 && errno == EINTR);
    if (written == -1) {
        const int saved_errno = errno;
        close(fd);
        return errno = saved_errno;
    }

    if (close(fd))
        return errno;

    /* Not all written?
     * It is okay if the last char, '\n' was not written. */
    if (written != (ssize_t)(q - p) &&
        written != (ssize_t)(q - 1 - p))
        return errno = EIO; /* Partial write, data not accepted! */

    return errno = 0;
}

Observe que quando fazemos o write() , verificamos que todos os caracteres (exceto a nova linha final) foram escritos. Este é o requisito de atomicidade que você precisa. Também gosto de ter cuidado e verifique se close() também não falha. (Embora isso não ocorra atualmente, é a única maneira de relatar certos erros, então eu gosto de estar preparado para o momento em que esses erros são relatados. Se eles ocorrerem.)

    
por 01.04.2016 / 15:24