我需要编写一个包含2个进程的程序,其中一个写入偶数,另一个写入不均匀的数字。在结果中,我必须按顺序从1到100。
我输入了这段代码,但是当涉及到处理部分时,它会卡在printProc()
函数中。我想问题是在管道中读写。
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int fd[2];
int printProc(int startNumber, int procNumber);
int main()
{
pid_t childpid;
pipe(fd);
int start = 0;
write(fd[0], &start, sizeof(start));
if ((childpid = fork()) == -1)
{
perror("fork");
}
if (childpid == 0)
{
printf("run child\n");
printProc(1, 0);
}
else
{
printf("run parent\n");
printProc(2, 1);
}
return 0;
}
int printProc(int startNumber, int procNumber)
{
FILE *f;
f = fopen("output.txt", "a+");
int num = startNumber;
int proc;
while (num <= 100)
{
read(fd[1], &proc, sizeof(proc));
if (proc == procNumber)
{
fprintf(f, "%d", num);
num = num + 2;
proc = (proc + 1) % 2;
write(fd[0], &proc, sizeof(proc));
}
}
return 0;
}
答案 0 :(得分:2)
我建议在这里使用互斥锁。您的关键部分将包含三个操作:
以下是实现该目的的代码:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <pthread.h>
#include <sys/mman.h>
int main() {
pthread_mutex_t *pmutex;
short * even;
pthread_mutexattr_t attrmutex;
pthread_mutexattr_init(&attrmutex);
pthread_mutexattr_setpshared(&attrmutex, PTHREAD_PROCESS_SHARED);
pmutex = mmap(NULL, sizeof(pthread_mutex_t), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
even = mmap(NULL, sizeof(short), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
pthread_mutex_init(pmutex, &attrmutex);
pthread_mutex_lock(pmutex);
*even = 0;
if(fork() == 0){
int a = 2;
while(a <= 100) {
pthread_mutex_lock(pmutex);
if(*even) {
printf("%d\n", a);
*even = 0;
a = a + 2;
}
pthread_mutex_unlock(pmutex);
}
return 0;
}else {
int a = 1;
printf("%d\n", a);
*even = 1;
pthread_mutex_unlock(pmutex);
a = a + 2;
while(a <= 99) {
pthread_mutex_lock(pmutex);
if(!*even) {
printf("%d\n", a);
*even = 1;
a = a + 2;
}
pthread_mutex_unlock(pmutex);
}
}
pthread_mutex_destroy(pmutex);
pthread_mutexattr_destroy(&attrmutex);
}
两个进程共享两个变量:pmutex
(用于同步)和even
(用于检查允许打印的进程)。
答案 1 :(得分:1)
你需要2个管道,当一个进程写入数字时,它会将一些数据写入一个管道,这样另一个进程就会知道它可以编写自己的数字等。
实施的例子:
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdbool.h>
int main(void) {
int parent_to_child[2];
int child_to_parent[2];
if (pipe(parent_to_child) == -1 || pipe(child_to_parent) == -1) {
perror("pipe");
return EXIT_FAILURE;
}
pid_t cpid = fork();
if (cpid == -1) {
perror("fork");
return EXIT_FAILURE;
}
if (cpid == 0) {
close(parent_to_child[1]);
close(child_to_parent[0]);
int i = 1;
bool buf;
ssize_t ret;
while ((ret = read(parent_to_child[0], &buf, sizeof buf)) > 0) {
fprintf(stdout, "%d ", i);
fflush(stdout);
if (write(child_to_parent[1], &buf, sizeof buf) != sizeof buf) {
break;
}
i += 2;
}
close(parent_to_child[0]);
close(child_to_parent[1]);
} else {
close(parent_to_child[0]);
close(child_to_parent[1]);
int i = 2;
bool buf = true;
ssize_t ret;
while (i <= 100 &&
write(parent_to_child[1], &buf, sizeof buf) == sizeof buf &&
(ret = read(child_to_parent[0], &buf, sizeof buf)) > 0) {
fprintf(stdout, i != 100 ? "%d " : "%d\n", i);
fflush(stdout);
i += 2;
}
close(parent_to_child[1]);
close(child_to_parent[0]);
}
}
答案 2 :(得分:1)
如果你想使用管道同步2个进程,你真的应该使用一对管道,前者由proc1读取并由proc2写入,后者由proc2读取并由proc1写入。从那里你将读写句柄传递给printProc
,这就是全部。
但是代码中还有另一个问题:在缓冲模式下使用fopen
)在两个进程中打开输出文件。所以每个进程都有自己的缓冲区。这两个缓冲区将被单独输入并且仅在关闭时写入文件,这不是您想要的:您必须在fork之前打开输出文件,并在非缓冲模式下使用它。
所以你的代码可能变成:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int printProc(int startNumber, FILE *f, int fdin, int fdout);
int main()
{
pid_t childpid;
int fd[4];
FILE *f;
pipe(fd);
pipe(fd + 2);
int start = 0;
write(fd[0], &start, sizeof(start));
f = fopen("output.txt", "w");
if (f == NULL) {
perror("Error opening file");
return 1;
}
setbuf(f, NULL); // use unbuffered mode for output.txt
if ((childpid = fork()) == -1)
{
perror("fork");
}
if (childpid == 0)
{
printf("run child\n");
printProc(1, f, fd[1], fd[2]);
}
else
{
printf("run parent\n");
printProc(2, f, fd[3], fd[0]);
}
fclose(f);
return 0;
}
int printProc(int num, FILE *f, int fdin, int fdout)
{
int proc;
while (num <= 100)
{
read(fdin, &proc, sizeof(proc));
fprintf(f, "%d\n", num);
num = num + 2;
write(fdout, &proc, sizeof(proc));
}
return 0;
}