我正在编写一个程序:
我该怎么做?到目前为止,我有:
#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;
}
它从文件中读取,写入另一个文件等,但没有同步 - 输出只是最后一行。
我该怎么做?
答案 0 :(得分:1)
此代码似乎有效。确保您在将其作为您自己的交付之前了解这一切。我调用了文件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