Cơ sở: Viết chương trình để truy vấn người dùng cho hai chuỗi đầu vào. Mỗi chuỗi đầu vào phải là lệnh unix, với các đối số được cho phép. Ví dụ: đầu vào 1 có thể là ls -l
và đầu vào 2 có thể là more
. Chương trình sau đó sẽ tạo một đường ống và hai tiến trình con. Quá trình con đầu tiên sẽ chạy lệnh được chỉ định trong đầu vào đầu tiên. Nó sẽ xuất ra ống thay vì đầu ra tiêu chuẩn. Quá trình con thứ hai sẽ chạy lệnh được chỉ định trong đầu vào thứ hai. Nó sẽ lấy đầu vào của nó từ đường ống chứ không phải đầu vào tiêu chuẩn. Quá trình cha mẹ sẽ chờ đợi trên hai đứa con của mình để hoàn thành, sau đó toàn bộ điều sẽ lặp lại. Việc thực hiện sẽ dừng khi biểu tượng '@' được nhập làm lệnh đầu tiên. Đây là mã tôi có:Đường ống và quy trình
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(){
/* Program Termination Symbol */
const char terminate = '@';
/* String delimiter */
const char delimiter = ' ';
/* Pipe file ID's */
int fileID[2];
/* Parent ID's */
int pid1, pid2;
/* String token */
char * token, * token2;
/* User input */
char * user_input, line[100];
user_input = (char *) malloc(100);
/* Unix Commands */
char * command1[10], *command2[10];
for (int i=0; i<10; i++)
{
command1[i] = (char *)malloc(100*sizeof(char));
command2[i] = (char *)malloc(100*sizeof(char));
}
/* Begin main program logic */
printf("Please enter the first command: \n");
user_input = gets(line);
while (user_input[0] != terminate)
{
token = (char *) malloc(100*sizeof(char));
for (int i=0; i<10; i++)
{
if (i == 0)
{
token = strtok(user_input, &delimiter);
} else {
token = strtok(NULL, &delimiter);
}
if (token != NULL)
{
strcpy(command1[i], token);
} else {
command1[i] = 0;
}
}
printf("Please enter the second command: \n");
user_input = gets(line);
token2 = (char *) malloc(100*sizeof(char));
for (int i=0; i<10; i++)
{
if (i == 0)
{
token2 = strtok(user_input, &delimiter);
} else {
token2 = strtok(NULL, &delimiter);
}
if (token2 != NULL)
{
strcpy(command2[i], token2);
} else {
command2[i] = 0;
}
}
/* Pipe and execute user commands */
/* Create pipe */
pipe(fileID);
/* Create child processes */
pid1 = fork();
if (pid1 != 0)
{
pid2 = fork();
}
/* First child process */
if (pid1 == 0)
{
dup2(fileID[1], 1);
execvp(command1[0], command1);
}
/* Second child process */
if (pid2 == 0)
{
dup2(fileID[0], 0);
execvp(command2[0], command2);
}
/* Wait for children to terminate */
wait(&pid1);
wait(&pid2);
/* Repeat */
printf("Please enter the first command: \n");
user_input = gets(line);
}
return 0;
}
Vấn đề tôi đang gặp phải là do sự chờ đợi của mình. Nếu tôi có cả hai, điều đó có ý nghĩa với tôi (một lần chờ đợi cho mỗi đứa trẻ) thì chương trình bị đóng băng sau khi thực hiện đường ống đầu tiên. Nếu tôi loại bỏ sự chờ đợi thứ hai, sau đó chương trình sẽ bắt đầu vòng lặp của nó một lần nữa, nhưng sẽ không chấp nhận đầu vào bàn phím khác hơn là nhập, và sẽ tạo ra một segfault. Vì vậy, với cả thời gian chờ, đầu vào và đầu ra là ...
Please enter the first command:
ls
Please enter the second command:
more
Pipe
Pipe.c
Pipe.c~
... và sau đó nó khóa lại. Nếu tôi xóa lần chờ thứ hai, đầu vào/đầu ra là ...
Please enter the first command:
ls
Please enter the second command:
more
Pipe
Pipe.c
Pipe.c~
Please enter the first command:
(I hit enter, nothing else will work)
Segmentation fault
Bất cứ ai có bất cứ đề xuất nào? Nó rõ ràng liên quan đến việc chờ đợi trên hai quy trình, nhưng tôi đang thua lỗ như thế nào để xử lý nó.
Chương trình này hiện đang hoạt động 100% - cảm ơn bạn rất nhiều vì sự giúp đỡ của bạn, tất cả mọi người! Stack overflow là một trong những tài nguyên tốt nhất trên internet. Cảm ơn tất cả các bạn rất nhiều vì đã dành thời gian để xem xét mã của tôi và cho tôi đề xuất của bạn.
Bạn chỉ cần đợi trẻ ở cuối đường ống. –
@PeterRitchie Xin lưu ý rằng thẻ bài tập về nhà đã không được chấp nhận (đọc phần mô tả). Cảm ơn. – Tim