From 0903b37b35f65e158d170f49c213a74abc36b6c5 Mon Sep 17 00:00:00 2001 From: flykhan Date: Fri, 18 Aug 2023 01:09:47 +0800 Subject: [PATCH] =?UTF-8?q?=E7=AE=A1=E9=81=93=E4=BD=9C=E4=B8=9A=E5=89=8D6?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- day4/homework/a.txt | 1 + day4/homework/h1.c | 47 ++++++++++++++++++++++++++ day4/homework/h2.c | 55 ++++++++++++++++++++++++++++++ day4/homework/h3.c | 72 +++++++++++++++++++++++++++++++++++++++ day4/homework/h4.c | 80 ++++++++++++++++++++++++++++++++++++++++++++ day4/homework/h5.c | 60 +++++++++++++++++++++++++++++++++ day4/homework/h6.c | 57 +++++++++++++++++++++++++++++++ day4/homework/h7.c | 6 ++++ day4/homework/test.c | 67 +++++++++++++++++++++++++++++++++++++ 9 files changed, 445 insertions(+) create mode 100644 day4/homework/a.txt create mode 100644 day4/homework/h1.c create mode 100644 day4/homework/h2.c create mode 100644 day4/homework/h3.c create mode 100644 day4/homework/h4.c create mode 100644 day4/homework/h5.c create mode 100644 day4/homework/h6.c create mode 100644 day4/homework/h7.c create mode 100644 day4/homework/test.c diff --git a/day4/homework/a.txt b/day4/homework/a.txt new file mode 100644 index 0000000..d7a8255 --- /dev/null +++ b/day4/homework/a.txt @@ -0,0 +1 @@ +hihao shijie diff --git a/day4/homework/h1.c b/day4/homework/h1.c new file mode 100644 index 0000000..00088a5 --- /dev/null +++ b/day4/homework/h1.c @@ -0,0 +1,47 @@ +// 创建一个无名管道,并在父子进程之间传递数据。 +#include +#include +#include +#include + +int main() +{ + int fd[2]; + int f = pipe(fd); + if (f == -1) + { + perror("pipe"); + return 1; + } + + int pid = fork(); + if (pid == 0) + { + // 子进程 + close(fd[1]); // 关闭写通道 + char buf[32] = ""; + int len = read(fd[0], buf, 32); + buf[strlen(buf) - 1] = '\0'; + + printf("子进程(%d)收到父进程(%d)数据: %s\n", getpid(), getppid(), buf); + close(fd[0]); + _exit(0); + } + else if (pid > 0) + { + // 父进程 + close(fd[0]); + printf("父进程正在写入数据\n"); + /* + 父进程在写入数据之后进行了sleep(2)的延迟操作,以确保子进程在读取之前有足够的时间启动。 + 这样可以避免子进程在尝试读取数据之前管道还没有数据可读的情况。 + */ + // sleep(2); + // char buf[32] = "hello pipe"; + char buf[32]; + fgets(buf, 32, stdin); + write(fd[1], buf, strlen(buf)); + close(fd[1]); + } + return 0; +} \ No newline at end of file diff --git a/day4/homework/h2.c b/day4/homework/h2.c new file mode 100644 index 0000000..7932fdf --- /dev/null +++ b/day4/homework/h2.c @@ -0,0 +1,55 @@ +// 创建两个子进程,一个子进程向管道写入数据,另一个子进程从管道读取数据。 +#include +#include +#include +#include +#include + +int main() +{ + int fd[2]; + int f = pipe(fd); + if (f == -1) + { + perror("pipe"); + return 1; + } + + int i = 0; + for (; i < 2; i++) + { + pid_t pid = fork(); + if (pid == 0) + break; // 子进程跳出循环 + } + + // 子进程1代码 + if (i == 0) + { + close(fd[0]); // 子进程1关闭管道读端 + + char msg[32] = ""; + printf("请在子进程 1 中输入一段内容: "); + scanf("%s", msg); + write(fd[1], msg, strlen(msg) + 1); // 包括'\0' , 写入管道 + close(fd[1]); // 关闭管道写端 + return 0; // 子进程1退出 + } + + // 子进程2代码 + else if (i == 1) + { + close(fd[1]); // 子进程2关闭管道写端 + + char buf[32] = ""; + int len = read(fd[0], buf, sizeof(buf)); + printf("子进程 2 收到子进程 1 数据: %s\n", buf); + close(fd[0]); // 关闭管道读端 + return 0; // 子进程2退出 + } + + // 父进程代码 + waitpid(0, NULL, 0); // 等待所有子进程退出 + + return 0; +} diff --git a/day4/homework/h3.c b/day4/homework/h3.c new file mode 100644 index 0000000..8252464 --- /dev/null +++ b/day4/homework/h3.c @@ -0,0 +1,72 @@ +// 创建两个子进程,一个子进程向从标准输入读取数据并向管道写入数据,另一个子进程从管道读取数据并输出标准设备。当输入的数据是bye时,则退出。父进程等待所有子进程退出。 +#include +#include +#include +#include +#include + +int main() +{ + int fd[2]; + int f = pipe(fd); + if (f == -1) + { + perror("pipe"); + _exit(1); + } + + int i = 0; + for (; i < 2; i++) + { + pid_t pid = fork(); + if (pid == 0) + break; // 子进程跳出循环 + } + + if (i == 0) + { + close(fd[0]); // 子进程1关闭管道读端 + + printf("请在子进程 1 中输入一段内容:\n"); + while (1) + { + char msg[32] = ""; + fgets(msg, 32, stdin); + msg[strcspn(msg, "\n")] = '\0'; // 去掉换行符 + + write(fd[1], msg, strlen(msg) + 1); // 包括'\0' , 写入管道 + if (strcmp(msg, "bye") == 0) + break; // 如果输入 "bye",子进程1退出循环 + } + + close(fd[1]); // 关闭管道写端 + _exit(0); // 子进程1退出 + } + else if (i == 1) + { + close(fd[1]); // 子进程2关闭管道写端 + + while (1) + { + char buf[32] = ""; + int len = read(fd[0], buf, 32); + if (len <= 0) + break; // 如果读取失败或到达文件末尾,子进程2退出循环 + if (strcmp(buf, "bye") == 0) + break; // 如果收到 "bye",子进程2退出循环 + printf("子进程 2 收到子进程 1 数据: %s\n", buf); + } + + close(fd[0]); // 关闭管道读端 + _exit(0); // 子进程2退出 + } + + while (1) + { + int p_id = waitpid(-1, NULL, 0); + if (p_id == -1) + break; // 等待所有子进程退出后,父进程退出循环 + } + + return 0; +} diff --git a/day4/homework/h4.c b/day4/homework/h4.c new file mode 100644 index 0000000..4374f26 --- /dev/null +++ b/day4/homework/h4.c @@ -0,0 +1,80 @@ +/* +创建一个父进程和两个子进程,父进程从标准输入读取数据,并通过管道发送给第一个子进程,第一个子进程将数据转换为大写并发送给第二个子进程,第二个子进程将数据输出到标准输出。 +【提示】定义两个无名管道,并在父进程进行两次fork()创建子进程 +*/ +#include +#include +#include +#include +#include + +int main() +{ + pid_t pid1, pid2; + int fd1[2], fd2[2]; + int f1 = pipe(fd1); + int f2 = pipe(fd2); + if (f1 == -1 || f2 == -1) + { + perror("pipe"); // 创建管道失败 + _exit(1); // 创建管道失败,退出 + } + + pid1 = fork(); + if (pid1 == 0) + { + close(fd1[1]); // 子进程1关闭管道写端 + + char buf[32] = ""; + int len = read(fd1[0], buf, sizeof(buf)); + printf("子进程 1 收到父进程数据: %s\n", buf); + + for (int i = 0; i < strlen(buf); i++) + { + if (buf[i] >= 'a' && buf[i] <= 'z') + buf[i] -= 32; + } + + write(fd2[1], buf, strlen(buf) + 1); // 包括'\0' , 写入管道 + close(fd2[1]); // 关闭管道写端 + _exit(0); // 子进程1退出 + } + + pid2 = fork(); + if (pid2 == 0) + { + close(fd2[1]); // 子进程2关闭管道写端 + + char buf[32] = ""; + int len = read(fd2[0], buf, sizeof(buf)); + printf("子进程 2 收到子进程 1 数据: %s\n", buf); + close(fd2[0]); // 关闭管道读端 + _exit(0); // 子进程2退出 + } + + close(fd1[0]); // 父进程关闭管道读端 + + char msg[32] = ""; + printf("请在父进程中输入一段内容: "); + scanf("%s", msg); + write(fd1[1], msg, strlen(msg) + 1); // 包括'\0' , 写入管道 + close(fd1[1]); // 关闭管道写端 + + /* + 参数说明: 0表示等待任意子进程退出,NULL表示不关心子进程退出状态,0表示阻塞等待 + 返回值: 返回退出的子进程的pid,如果没有子进程退出,则返回-1 + 阻塞: 父进程等待子进程退出,子进程退出后,父进程才会继续执行 + 非阻塞: 父进程不等待子进程退出,子进程退出后,父进程也会继续执行 + 1 表示等待第一个子进程退出; 2 表示等待第二个子进程退出 + -1 表示等待任意子进程退出 + WNOHANG 表示非阻塞等待 + WUNTRACED 表示如果子进程进入暂停状态,那么父进程也进入暂停状态 + WCONTINUED 表示如果子进程进入继续状态,那么父进程也进入继续状态 + WIFEXITED(status) 如果子进程正常退出,返回非0值 + WEXITSTATUS(status) 如果WIFEXITED(status)非0值,返回子进程的退出状态 + WIFSIGNALED(status) 如果子进程是因为信号而退出,返回非0值 + */ + waitpid(0, NULL, 0); // 等待所有子进程退出 + + return 0; +} \ No newline at end of file diff --git a/day4/homework/h5.c b/day4/homework/h5.c new file mode 100644 index 0000000..1c3727f --- /dev/null +++ b/day4/homework/h5.c @@ -0,0 +1,60 @@ +// 创建一个父进程和一个子进程,父进程从文件读取数据,并通过管道发送给子进程,子进程将数据输出到标准输出。 +// 例如:父进程从文件读取到的数据为:hello world,子进程将输出:hello world +#include +#include +#include +#include +#include +#include + +int main() +{ + pid_t pid; + int fd[2]; + int f = pipe(fd); + if (f == -1) + { + perror("pipe"); // 创建管道失败 + _exit(1); // 创建管道失败,退出 + } + + pid = fork(); + if (pid == 0) + { + close(fd[1]); // 子进程关闭管道写端 + + char buf[32] = ""; + int len = read(fd[0], buf, sizeof(buf)); + // buf[len] = '\0'; // 不加'\0',父进程读取到的数据会有乱码 + printf("子进程收到父进程数据: %s", buf); + + close(fd[0]); // 关闭管道读端 + _exit(0); // 子进程退出 + } + + close(fd[0]); // 父进程关闭管道读端 + + int fd_file = open("a.txt", O_RDONLY); // 打开文件 + if (fd_file == -1) + { + perror("open"); + _exit(1); + } + + char buf[32] = ""; + int len = read(fd_file, buf, sizeof(buf)); + if (len == -1) + { + perror("read"); + _exit(1); + } + + // 不加'\0',子进程读取到的数据会有乱码 + write(fd[1], buf, strlen(buf) /* + 1 */); // 包括'\0' , 写入管道 + + close(fd[1]); // 关闭管道写端 + close(fd_file); + waitpid(0, NULL, 0); // 等待子进程退出 + + return 0; +} \ No newline at end of file diff --git a/day4/homework/h6.c b/day4/homework/h6.c new file mode 100644 index 0000000..ee0a52f --- /dev/null +++ b/day4/homework/h6.c @@ -0,0 +1,57 @@ +// 创建两个子进程,一个子进程向有名管道写入数据,另一个子进程从有名管道读取数据。 +#include +#include +#include +#include +#include +#include +#include +#include + +int main() +{ + if (mkfifo("fifo", 0644) == -1) // 创建有名管道 + { + // 如果有名管道已经存在,不报错 + // 如果是其他错误,报错 + if (errno != EEXIST) + { + perror("mkfifo"); + _exit(1); + } + } + + int fd = open("fifo", O_RDWR); // 打开有名管道 + if (fd == -1) + { + perror("open"); + _exit(1); + } + + int i = 0; + for (; i < 2; i++) + { + pid_t pid = fork(); + if (pid == 0) + break; // 子进程跳出循环 + } + + if (i == 0) + { + char msg[32] = ""; + printf("请在子进程 1 中输入一段内容: "); + scanf("%s", msg); + write(fd, msg, strlen(msg) + 1); // 包括'\0' , 写入管道 + } + else if (i == 1) + { + char buf[32] = ""; + int len = read(fd, buf, sizeof(buf)); + printf("子进程 2 收到子进程 1 数据: %s\n", buf); + } + + close(fd); // 关闭管道 + waitpid(0, NULL, 0); + + return 0; +} \ No newline at end of file diff --git a/day4/homework/h7.c b/day4/homework/h7.c new file mode 100644 index 0000000..283ea53 --- /dev/null +++ b/day4/homework/h7.c @@ -0,0 +1,6 @@ +// 创建父子进程, 在父进程中输入命令,在子进程中执行,并将执行结果发送给父进程,父进程进行打印输出。 +#include +#include +#include +#include +#include diff --git a/day4/homework/test.c b/day4/homework/test.c new file mode 100644 index 0000000..304e04a --- /dev/null +++ b/day4/homework/test.c @@ -0,0 +1,67 @@ +#include +#include +#include +#include +#include + +int main() +{ + int fd[2]; + int f = pipe(fd); + if (f == -1) + { + perror("pipe"); + _exit(1); + } + + int i = 0; + for (; i < 2; i++) + { + pid_t pid = fork(); + if (pid == 0) + break; + } + + if (i == 0) + { + close(fd[0]); + printf("请在子进程 1 中输入一段内容:\n"); + while (1) + { + char msg[32] = ""; + fgets(msg, 32, stdin); + msg[strcspn(msg, "\n")] = '\0'; // 去掉换行符 + + write(fd[1], msg, strlen(msg) + 1); // 包括'\0' , 写入管道 + if (strcmp(msg, "bye") == 0) + break; + } + close(fd[1]); + _exit(0); + } + else if (i == 1) + { + close(fd[1]); + while (1) + { + char buf[32] = ""; + int len = read(fd[0], buf, 32); + if (len <= 0) + break; + if (strcmp(buf, "bye") == 0) + break; + printf("子进程 2 收到子进程 1 数据: %s\n", buf); + } + close(fd[0]); + _exit(0); + } + + while (1) + { + int p_id = waitpid(-1, NULL, 0); + if (p_id == -1) + break; + } + + return 0; +}