Как правильно ожидать переднего плана/фоновых процессов в моей собственной оболочке в C?

tl; dr
YearQuarter
.from(
    LocalDate.of( 2018 , 1 , 23 ) 
)

ThreeTen-Extra

Ответ от abdmob правильный: использование java.time является мудрым путь.

Кроме того, проект ThreeTen-Extra расширяет java.time дополнительными классами. Этот проект является полигоном для возможных будущих дополнений к java.time.

Его полезные классы включают:

Текущий квартал

Чтобы получить текущий квартал, укажите часовой пояс. Определение квартала означает определение даты. А определение даты означает указание часового пояса. В любой момент времени дата меняется по всему земному шару в зависимости от зоны. Укажите, используя собственное имя часового пояса в форме continent/region. Никогда не используйте 3-4-буквенные сокращения, такие как EST или IST.

ZoneId z = ZoneId.of( "America/Montreal" );
YearQuarter yq = YearQuarter.now( z );

С учетом java.util.Date

Если дано java.util.Date, сначала преобразуйте в тип java.time. Класс Instant представляет момент на временной шкале в UTC с разрешением наносекунд .

Instant instant = myUtilDate.toInstant();

Назначьте часовой пояс, чтобы получить ZoneDateTime.

ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone( z );

Создать YearQuarter из этого ZonedDateTime.

YearQuarter yq = YearQuarter.from( zdt );

Используйте в своем коде

Вы должны передавать экземпляры YearQuarter, а не просто числа или строки. Использование объектов обеспечивает безопасность типов, гарантирует допустимые значения и делает ваш код более самодокументируемым.

8
задан Community 23 May 2017 в 12:08
поделиться

3 ответа

В waitpid () есть различные варианты, которые могут вам помочь (цитаты из стандарта POSIX):

WCONTINUED

Функция waitpid () должна сообщать о состоянии любого продолжающегося дочернего процесса, указанного в pid, о статусе которого не сообщалось с тех пор, как он продолжил работу после остановки управления заданием.

WNOHANG

Функция waitpid () не должна приостанавливать выполнение вызывающего потока, если статус не доступен немедленно для одного из дочерних процессов, указанных в pid.

В частности, WNOHANG позволит вам увидеть, есть ли - это любые трупы, которые нужно собрать, не заставляя ваш процесс блокироваться в ожидании трупа.

Если для вызывающего процесса задано значение SA_NOCLDWAIT или для SIGCHLD задано значение SIG_IGN, и процесс не имеет ожидаемых дочерних процессов, которые были преобразованы в процессы-зомби, вызывающий поток должен блокироваться до тех пор, пока все дочерние элементы процесса, содержащего вызывающий поток, не завершатся, а wait () и waitpid () завершатся ошибкой и установят errno в [ECHILD].

Вероятно, вы не хотите игнорировать SIGCHLD и т. Д., И ваш обработчик сигналов, вероятно, должен устанавливать флаг, сообщающий вашему основному циклу «Oops; there»

5
ответ дан 5 December 2019 в 19:02
поделиться

Вместо использования глобальной переменной я подумал о другом решении:

if(!background) {
    signal(SIGCHLD, NULL);

    waitpid(pid, NULL, 0);

    signal(SIGCHLD, childSignalHandler);
}

Если я запускаю процесс переднего плана, «удалите» обработчик для SIGCHLD, чтобы он не вызывался. Затем, после waitpid (), снова установите обработчик. Таким образом, будут обрабатываться только фоновые процессы.

Как вы думаете, что-то не так с этим решением?

0
ответ дан 5 December 2019 в 19:02
поделиться

Это должно помочь вам начать работу. Основное отличие состоит в том, что я избавился от дочернего обработчика и добавил waitpid в основной цикл с некоторой обратной связью. Протестировано и работает, но, очевидно, требуется больше TLC.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <wait.h>
#include <signal.h>
#include <sys/types.h>

int main(int argc, char **argv) {
        char bBuffer[BUFSIZ], *pArgs[10], *aPtr = NULL, *sPtr;
        int background;
        ssize_t rBytes;
        int aCount;
        pid_t pid;
        int status;
        while(1) {
                pid = waitpid(-1, &status, WNOHANG);
                if (pid > 0)
                        printf("waitpid reaped child pid %d\n", pid);
                write(1, "\e[1;31mmyBash \e[1;32m# \e[0m", 27);
                rBytes = read(0, bBuffer, BUFSIZ-1);
                if(rBytes == -1) {
                        perror("read");
                        exit(1);
                }
                bBuffer[rBytes-1] = '\0';
                if(!strcasecmp(bBuffer, "exit")) 
                        exit(0);
                sPtr = bBuffer;
                aCount = 0;
                do {
                        aPtr = strsep(&sPtr, " ");
                        pArgs[aCount++] = aPtr;
                } while(aPtr);
                background = (strcmp(pArgs[aCount-2], "&") == 0);
                if (background)
                        pArgs[aCount-2] = NULL;
                if (strlen(pArgs[0]) > 1) {
                        pid = fork();
                        if (pid == -1) {
                                perror("fork");
                                exit(1);
                        } else if (pid == 0) {
                                execvp(pArgs[0], pArgs);
                                exit(1);
                        } else if (!background) {
                                pid = waitpid(pid, &status, 0);
                                if (pid > 0)
                                        printf("waitpid reaped child pid %d\n", pid);
                        }
                }
        }
        return 0;
}

РЕДАКТИРОВАТЬ: Добавить обратно в обработку сигналов несложно с waitpid () с использованием WNOHANG. Это так же просто, как переместить материал waitpid () из верхней части цикла в обработчик сигнала. Однако вы должны знать о двух вещах:

Во-первых, даже «передний план» процессы будут отправлять SIGCHLD. Поскольку может быть только один процесс переднего плана, вы можете просто сохранить pid переднего плана (родительское возвращаемое значение из fork () ) в переменной, видимой обработчику сигнала, если вы хотите выполнить особую обработку переднего плана по сравнению с фоном. .

Во-вторых, в настоящее время вы выполняете блокирующий ввод-вывод на стандартный ввод ( read () в верхней части основного цикла). С большой вероятностью вы будете заблокированы на read () при возникновении SIGCHLD, что приведет к прерыванию системного вызова. В зависимости от ОС он может автоматически перезапустить системный вызов или отправить сигнал, который необходимо обработать.

2
ответ дан 5 December 2019 в 19:02
поделиться
Другие вопросы по тегам:

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