簡體   English   中英

使用USR信號同步過程

[英]Synchronizing processes using USR signals

我正在編寫一個程序,其中:

  • 主進程逐行讀取文件,並在每次替換舊行時將其寫入另一個文件
  • 子進程讀取另一個文件,並在控制台上輸出行

我怎樣才能做到這一點? 到目前為止,我有:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>

int main(int argc, char **argv)
{
    int pid, c;
    FILE *fpr, *fpw;
    char str[512];

    if((pid = fork()) == 0)
    {
        fpr = fopen("bufor", "r");
        if(fpr == NULL)
            exit(EXIT_FAILURE);

        while(fscanf(fpr, "%[^\n]\n", str) != EOF)
        {
            printf("%s", str);
        }

        fclose(fpr);
        exit(0);
    }

    fpr = fopen("/etc/profile", "r");
    if(fpr == NULL)
        exit(EXIT_FAILURE);

    if(fpr)
    {
        while(fscanf(fpr, "%[^\n]\n", str) != EOF)
        {
            fpw = fopen("bufor", "w+");
            if(sizeof(str) > 0)
            {
                fputs(str, fpw);
            }
            fclose(fpw);
        }
        fclose(fpr);
    }

    return 0;
}

它從文件讀取,寫入另一個文件等,但是沒有同步-輸出僅是最后一行。

我怎樣才能做到這一點?

此代碼似乎有效。 確保自己理解所有內容,然后再將其作為自己的內容進行傳遞。 我調用了文件sigsync.c ,因此調用了程序sigsync ,因此選擇了環境變量的名稱。

匯編:

gcc -g -O3 -std=gnu11 -Wall -Wextra -Wmissing-prototypes \
    -Wstrict-prototypes -Werror sigsync.c -o sigsync 

碼:

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

static int verbose = 0;
static volatile sig_atomic_t sig_num = 0;

static void sigusr1(int signum)
{
    sig_num = signum;
}

static void be_childish(const char *file, pid_t parent)
{
    char str[512];
    FILE *fpr = fopen(file, "r");
    if (fpr == NULL)
    {
        fprintf(stderr, "Failed to open file %s for reading\n", file);
        exit(EXIT_FAILURE);
    }

    while (1)
    {
        rewind(fpr);
        pause();
        if (verbose)
            printf("Child:  got %d\n", sig_num);
        while (fscanf(fpr, "%511[^\n]\n", str) == 1)
            printf("%s\n", str);
        kill(parent, SIGUSR1);
        sig_num = 0;
    }

    /*NOTREACHED*/
    fclose(fpr);
}

static void be_parental(const char *file, pid_t child)
{
    char str[512];
    const char profile[] = "/etc/profile";

    FILE *fpr = fopen(profile, "r");
    if (fpr == NULL)
    {
        fprintf(stderr, "Failed to open file %s for reading\n", profile);
        exit(EXIT_FAILURE);
    }

    while (fscanf(fpr, "%511[^\n]\n", str) != EOF)
    {
        if (strlen(str) > 0)
        {
            FILE *fpw = fopen(file, "w");
            if (fpw == 0)
            {
                fprintf(stderr, "Failed to open file %s for reading\n", profile);
                kill(child, SIGTERM);
                exit(EXIT_FAILURE);
            }
            fprintf(fpw, "%s\n", str);
            fclose(fpw);
            kill(child, SIGUSR1);
            pause();
            if (verbose)
                printf("Parent: got %d\n", sig_num);
            sig_num = 0;
        }
    }
    fclose(fpr);
    kill(child, SIGTERM);
}

int main(void)
{
    int child;
    int parent = getpid();
    const char filename[] = "bufor";

    /* Make sure file exists and is empty */
    FILE *fp = fopen(filename, "w");
    if (fp == 0)
    {
        fprintf(stderr, "Failed to open file %s for writing\n", filename);
        exit(EXIT_FAILURE);
    }
    fclose(fp);

    if (getenv("SIGSYNC_VERBOSE") != 0)
        verbose = 1;

    struct sigaction sa;
    sa.sa_handler = sigusr1;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;
    if (sigaction(SIGUSR1, &sa, 0) != 0)
    {
        fprintf(stderr, "Failed to set signal handler\n");
        exit(EXIT_FAILURE);
    }

    if ((child = fork()) < 0)
    {
        fprintf(stderr, "Failed to fork\n");
        exit(EXIT_FAILURE);
    }
    else if (child == 0)
        be_childish(filename, parent);
    else
        be_parental(filename, child);

    return 0;
}

樣本輸出:

請注意,前導空格已完全刪除。 父級讀取/etc/profile中的代碼可以做到這一點,其原因很微妙。 "%511[^\\n]\\n"格式不會跳過開頭的空格,但是末尾的\\n不會被視為“僅匹配換行符”,而是被視為“匹配一系列空格”。 這意味着它將跳過換行符和下一行的空白行。 要保留空間,請使用fgets()getline()而不是fscanf() 在具有GCC 5.1.0的Ubuntu 14.04衍生產品上進行了測試。

# /etc/profile: system-wide .profile file for the Bourne shell (sh(1))
# and Bourne compatible shells (bash(1), ksh(1), ash(1), ...).
umask 027
if [ "$PS1" ]; then
if [ "$BASH" ]; then
PS1='\u@\h:\w\$ '
if [ -f /etc/bash.bashrc ]; then
. /etc/bash.bashrc
fi
else
if [ "`id -u`" -eq 0 ]; then
PS1='# '
else
PS1='$ '
fi
fi
fi
if [ -d /etc/profile.d ]; then
for i in /etc/profile.d/*.sh; do
if [ -r $i ]; then
. $i
fi
done
unset i
fi

暫無
暫無

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

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