Как правильно использовать подпись ()с SA _RESTART?

Простое (r )решение, которое загружает весь файл в память:

sed -z 's/\\\n//g' file                   # GNU sed 4.2.2+.

Или еще короткий, который работает с пониманием (вывода )строк (синтаксиса GNU):

sed ':x;/\\$/{N;bx};s/\\\n//g' file

На одной строке (Синтаксис POSIX):

sed -e :x -e '/\\$/{N;bx' -e '}' -e 's/\\\n//g' file

Или используйте awk (, если файл слишком велик и не помещается в памяти):

awk '{a=sub(/\\$/,"");printf("%s%s",$0,a?"":RS)}' file
-1
26.07.2020, 01:17
1 ответ

Если я понимаю, что вам нужно, вы хотите иметь возможность обрабатывать (1 )ввод с клавиатуры, (2 )сигналы и (3 )потенциально другие источники событий. Если это так, то это может быть началом того, что вам нужно:

#include <errno.h>
#include <poll.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

static int pipe_fds[2];

static void handler(const int signo)
{
    #define msg "received SIGTSTP\n"
    write(pipe_fds[1], msg, strlen(msg));
    #undef msg
}

int main(void)
{
    if (pipe(pipe_fds) < 0) {
        perror("pipe");
    }

    struct sigaction sa = {
       .sa_handler = handler,
       .sa_flags = SA_RESTART | SA_NOCLDSTOP,
    };

    if (sigemptyset(&sa.sa_mask) < 0) {
        perror("sigemptyset");
        return 1;
    }

    if (sigaction(SIGTSTP, &sa, NULL) < 0) {
        perror("sigaction");
        return 1;
    }

    struct pollfd fds[] = {
        {
           .fd = STDIN_FILENO,
           .events = POLL_IN,
        },
        {
           .fd = pipe_fds[0],
           .events = POLL_IN,
        },
    };

    const int num_fds = 2;
    char buffer[1024] = {};

    for (;;) {
        const int ret = poll(fds, num_fds, -1);
        if (ret < 0) {
            if (errno == EINTR) {
                // Receiving SIGTSTP can cause poll() to return
                // -1 with errno = EINTR.  Ignore that.
                continue;
            }
            perror("poll");
            return 1;
        }

        for (int i = 0; i < num_fds; ++i) {
            if (fds[i].revents & POLL_IN) {
                const int count = read(fds[i].fd, buffer, sizeof(buffer) - 1);

                buffer[count - 1] = '\0';
                printf("Read '%s' from file descriptor %d\n", buffer, fds[i].fd);
            }
        }
    }

    return 0;
}

Функция main()начинается с создания канала; программа использует конвейер для связи между функцией обработчика сигнала (в контексте сигнала )и основной программой. Затем он устанавливает обработчик сигнала для сигнала SIGTSTP, как вы описали выше.

После этого создается массив из struct pollfdс именем fds. Каждая запись в этом массиве соответствует файловому дескриптору, активность которого интересует программу. Первая запись в массиве — это дескриптор файла для стандартного ввода. Второй — считываемый -конец упомянутой выше -трубы. Если вы хотите расширить этот пример для обработки других источников событий ---событий, связанных с файловыми дескрипторами ---, то это можно сделать здесь, просто добавьте дополнительные элементы в массив fdsс соответствующим файлом дескрипторы.

Затем он входит в цикл событий, используя poll. С тайм-аутом -1pollбудет блокироваться до тех пор, пока (1 )он не получит активность на одном из зарегистрированных файловых дескрипторов или (2 )сигнал не прервет его (, такой как получениеSIGTSTP). Поэтому программа проверяет возвращаемое значение pollи, если оно меньше 0, явно проверяет и игнорирует ошибку EINTR(, прерванную системным вызовом ).

Если poll()возвращается из-за активности, то поле reventsсвязанного struct pollfdбудет помечено соответствующим образом. Затем он прочитает соответствующий дескриптор файла и напечатает сообщение.

Вот пример запуска:

$./a.out
Hello!
Read 'Hello!' from file descriptor 0
How are you?
Read 'How are you?' from file descriptor 0
^ZRead 'received SIGTSTP' from file descriptor 3
Good
Read 'Good' from file descriptor 0
^C
$

В примере запуска он читал Hello!, а затем How are you?с клавиатуры. В обоих случаях программа ответила, прочитав то, что я набрал, и распечатав ответ. Следующий,Я сгенерировал сигнал SIGTSTP, он прочитал received SIGTSTPиз конвейера и напечатал ответ. Затем он прочитал Goodс клавиатуры и напечатал ответ. В конце концов я прервал программу с помощью Ctrl-C, и программа завершилась.

Обратите внимание, что readможет возвращать меньше доступных байтов. Для простоты я не проверял это условие. Возможно, вы захотите это сделать в зависимости от источников событий, которые вы хотите обработать.

2
18.03.2021, 23:16

Теги

Похожие вопросы