This commit is contained in:
flykhan 2023-08-17 19:22:02 +08:00
parent dea9717412
commit 15ef646981
17 changed files with 645 additions and 0 deletions

92
day4/bbs_bob.c Normal file
View File

@ -0,0 +1,92 @@
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <errno.h>
#include <string.h>
// 单机聊天工具 (bob方)
int main(int argc, char const *argv[])
{
// 使用方法 gcc xx.c -D CREATE_FIFO 会在运行时执行预处理区段
#ifdef CREATE_FIFO
mkfifo("fifo_bob_to_lucy", 0644);
mkfifo("fifo_lucy_to_bob", 0644);
#endif
if (mkfifo("fifo_bob_to_lucy", 0644) != -1)
{
if (errno != EEXIST)
{
perror("fifo_bob_to_lucy");
return 1;
}
}
if (mkfifo("fifo_lucy_to_bob", 0644) != -1)
{
if (errno != EEXIST)
{
perror("fifo_lucy_to_bob");
return 1;
}
}
int i = 0;
for (; i < 2; i++)
{
int pid = fork();
if (pid == 0)
break;
}
if (i == 0)
{
// 第一个子进程
// 从键盘输入数据并发送给对方 (bob -> lucy)
int fd = open("fifo_bob_to_lucy", O_WRONLY); // 只写消息
while (1)
{
char buf[128] = {};
int len = read(STDIN_FILENO, buf, 128);
buf[len - 1] = '\0';
write(fd, buf, len);
if (strcmp(buf, "bye") == 0)
{
break;
}
}
close(fd);
_exit(0);
}
else if (i == 1)
{
// 第二个进程,读数据 (lucy -> bob)
int fd = open("fifo_lucy_to_bob", O_RDONLY);
while (1)
{
char buf[128] = "";
int len = read(fd, buf, 128);
if (len <= 0)
break;
printf("接收 Lucy: %s\n", buf);
}
close(fd);
_exit(0);
}
else
{
// 主进程
while (1)
{
// int status;
int pid_ = waitpid(0, NULL, WNOHANG);
if (pid_ == -1)
{
// 所有子进程都已经退出
break;
}
}
}
return 0;
}

92
day4/bbs_lucy.c Normal file
View File

@ -0,0 +1,92 @@
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <errno.h>
#include <string.h>
// 单机聊天工具 (lucy方)
int main(int argc, char const *argv[])
{
// 使用方法 gcc xx.c -D CREATE_FIFO 会在运行时执行预处理区段
#ifdef CREATE_FIFO
mkfifo("fifo_bob_to_lucy", 0644);
mkfifo("fifo_lucy_to_bob", 0644);
#endif
if (mkfifo("fifo_bob_to_lucy", 0644) != -1)
{
if (errno != EEXIST)
{
perror("fifo_bob_to_lucy");
return 1;
}
}
if (mkfifo("fifo_lucy_to_bob", 0644) != -1)
{
if (errno != EEXIST)
{
perror("fifo_lucy_to_bob");
return 1;
}
}
int i = 0;
for (; i < 2; i++)
{
int pid = fork();
if (pid == 0)
break;
}
if (i == 0)
{
// 第一个子进程
// 从键盘输入数据并发送给对方 (lucy -> bob)
int fd = open("fifo_lucy_to_bob", O_WRONLY); // 只写消息
while (1)
{
char buf[128] = {};
int len = read(STDIN_FILENO, buf, 128);
buf[len - 1] = '\0';
write(fd, buf, len);
if (strcmp(buf, "bye") == 0)
{
break;
}
}
close(fd);
_exit(0);
}
else if (i == 1)
{
// 第二个进程,读数据 (bob -> lucy)
int fd = open("fifo_bob_to_lucy", O_RDONLY);
while (1)
{
char buf[128] = "";
int len = read(fd, buf, 128);
if (len <= 0)
break;
printf("接收 Bob: %s\n", buf);
}
close(fd);
_exit(0);
}
else
{
// 主进程
while (1)
{
// int status;
int pid_ = waitpid(0, NULL, WNOHANG);
if (pid_ == -1)
{
// 所有子进程都已经退出
break;
}
}
}
return 0;
}

38
day4/demo1.c Normal file
View File

@ -0,0 +1,38 @@
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <fcntl.h>
int main(int argc, char const *argv[])
{
int fd[2];
if (pipe(fd) == -1)
{
perror("pipe");
return 1;
}
pid_t pid = fork();
if (pid == 0)
{
close(fd[1]);
dup2(fd[0], 0); // 0 -> fd[0] ,标准输入设备改为管道
execlp("grep", "grep", "fish", NULL);
close(fd[0]);
_exit(0);
}
else if (pid > 0) // 父进程
{
close(fd[0]); // 关闭读
// 将命令执行结果写入管道中
dup2(fd[1], 1); // 1 -> fd[1] ,标准输出设备改为管道
execlp("ps", "ps", "-A", NULL);
close(fd[1]);
// wait(pid);
}
return 0;
}

39
day4/demo2.c Normal file
View File

@ -0,0 +1,39 @@
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <fcntl.h>
int main(int argc, char const *argv[])
{
int fd[2];
if (pipe(fd) == -1)
{
perror("pipe");
return 1;
}
pid_t pid = fork();
if (pid == 0)
{
close(fd[0]); // 关闭读
// 重定向标准输出到管道
dup2(fd[1], 1);
execlp("expr", "expr", "4", "+", "5", NULL);
close(fd[1]);
_exit(0);
}
else if (pid > 0) // 父进程
{
close(fd[1]); // 关闭写
char buf[10] = {};
int len = read(fd[0], buf, 10);
buf[len - 1] = '\0';
printf("读取子进程发送的数据: %s\n", buf);
close(fd[0]);
}
return 0;
}

35
day4/fifo_read.c Normal file
View File

@ -0,0 +1,35 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
int main()
{
// 创建 fifo 的有名(文件名)管道 if (mkfifo("myfifo", 0755) != 0)
if (mkfifo("myfifo", 0755) != 0)
{
if (errno != EEXIST)
{
perror("mkfifo");
return 1;
}
}
printf("准备以只读方式打开 myfifo\n");
int fd = open("myfifo", O_RDONLY);
printf("open myfifo fd = %d\n", fd);
int n = 1;
while (1)
{
char buf[32] = "";
int len = read(fd, buf, 32); // 阻塞(写进程运行期间),非阻塞(没有写进程运行)
buf[len - 1] = '\0';
printf("第%d次读取的数据(%d Bytes): %s\n", n++, len, buf);
sleep(1);
}
close(fd);
return 0;
}

35
day4/fifo_read_2.c Normal file
View File

@ -0,0 +1,35 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
int main()
{
// 创建 fifo 的有名(文件名)管道 if (mkfifo("myfifo", 0755) != 0)
if (mkfifo("myfifo", 0755) != 0)
{
if (errno != EEXIST)
{
perror("mkfifo");
return 1;
}
}
printf("准备以只读方式打开 myfifo\n");
int fd = open("myfifo", O_RDONLY | O_NONBLOCK); // 非阻塞
printf("open myfifo fd = %d\n", fd);
int n = 1;
while (1)
{
char buf[32] = "";
int len = read(fd, buf, 32); // 阻塞(写进程运行期间),非阻塞(没有写进程运行)
buf[len - 1] = '\0';
printf("第%d次读取的数据(%d Bytes): %s\n", n++, len, buf);
sleep(1);
}
close(fd);
return 0;
}

30
day4/fifo_write.c Normal file
View File

@ -0,0 +1,30 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
int main()
{
// 创建 fifo 的有名(文件名)管道
if (mkfifo("myfifo", 0755) != 0)
{
if (errno != EEXIST)
{
perror("mkfifo");
return 1;
}
}
printf("准备以只写方式打开 myfifo\n");
int fd = open("myfifo", O_WRONLY);
printf("open myfifo fd = %d\n", fd);
sleep(3); // 阻塞 5 秒
close(fd);
return 0;
}

38
day4/fifo_write_2.c Normal file
View File

@ -0,0 +1,38 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
int main()
{
// 创建 fifo 的有名(文件名)管道
if (mkfifo("myfifo", 0755) != 0)
{
// 管道文件已经存在,代码将继续执行后面的部分,其他错误报错
// 如果errno等于EEXIST则表示管道文件已经存在代码将继续执行后面的部分
if (errno != EEXIST)
{
perror("mkfifo");
return 1;
}
}
printf("准备以只写方式打开 myfifo\n");
int fd = open("myfifo", O_WRONLY | O_NONBLOCK);
if (fd == -1)
{
perror("open");
return 1;
}
printf("open myfifo fd = %d\n", fd);
sleep(3); // 阻塞 5 秒
close(fd);
return 0;
}

14
day4/file1.c Normal file
View File

@ -0,0 +1,14 @@
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{
close(1); // 关闭标准输出描述符
int fd = open("a.txt", O_WRONLY | O_CREAT | O_APPEND, 0644);
printf("hello fd\n"); // fd 描述符会变为 1 ,printf 回答引导 fd 对应文件中
return 0;
}

20
day4/file2.c Normal file
View File

@ -0,0 +1,20 @@
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{
int fd = open("a.txt", O_WRONLY | O_CREAT | O_APPEND, 0644);
printf("新打开的hello fd\n"); // fd 描述符会变为 1 ,printf 回答引导 fd 对应文件中
close(1); // 关闭标准输出文件描述符为1
int newfd = dup(fd); // 1->a.txt会分配当前最小可用的文件描述符(这个时候标准输出1的描述符空闲)即拿到文件描述符1
// 下面的打印(写入)会重定向到 a.txt 文件中
printf("newfd = %d\n", newfd);
printf("hahah\n");
close(fd);
printf("yes\n");
return 0;
}

20
day4/file3_dup2.c Normal file
View File

@ -0,0 +1,20 @@
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{
int fd = open("a.txt", O_WRONLY | O_CREAT | O_APPEND, 0644);
printf("新打开的hello fd\n"); // fd 描述符会变为 1 ,printf 回答引导 fd 对应文件中
// dup2 会自动关闭 newfd即关闭 1 标准输出
int newfd = dup2(fd, 1); // 1->a.txt, 会将新的 fd 描述符值为 1
close(fd);
// 下面的打印(写入)会重定向到 a.txt 文件中
printf("newfd = %d\n", newfd);
printf("no\n");
printf("good\n");
return 0;
}

21
day4/file4_0.c Normal file
View File

@ -0,0 +1,21 @@
// 配合file4使用
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{
// 设置 1 的 close_on_exec 打开状态(默认为关闭)
int flags;
flags = fcntl(1, F_GETFD);
flags |= FD_CLOEXEC;
// flags &= ~FD_CLOEXEC; // 关闭 FD_CLOEXEC 标志位
fcntl(1, F_SETFD, flags);
execl("./file4_1", "file4_1", NULL); // 当 file4_1 存在时会切换到file4_1运行不会继续执行本程序后续行内容
printf("file4_0"); // 当file4_1不存在时才会执行到这里
return 0;
}

11
day4/file4_1.c Normal file
View File

@ -0,0 +1,11 @@
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{
printf("hi, file4_1");
return 0;
}

45
day4/pipe1.c Normal file
View File

@ -0,0 +1,45 @@
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>
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[64] = {};
int len = read(fd[0], buf, 64); // 可能会阻塞,数据为空时会阻塞
printf("%d 子进程读取到: %s\n", getpid(), buf);
// 关闭使用完之后,记得关闭
close(fd[0]); // 关闭读管道
_exit(0);
}
else if (pid > 0)
{
// 父进程,写
// 关闭读通道
close(fd[0]);
printf("父进程(%d)等待3秒向子进程(%d)写数据\n", getpid(), pid);
sleep(3);
char buf[64] = "hello,flykhan";
write(fd[1], buf, strlen(buf));
// 关闭写通道
close(fd[1]);
}
return 0;
}

7
day4/pipe3.c Normal file
View File

@ -0,0 +1,7 @@
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main()
{
}

53
day4/pipe4.c Normal file
View File

@ -0,0 +1,53 @@
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>
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]);
for (int i = 0; i < 3; i++)
{
char buf[1024] = {};
int len = read(fd[0], buf, 1024); // 可能会阻塞,数据为空时会阻塞
buf[len - 1] = '\0';
printf("%d 子进程读取到: %s ,数据大小为 %d\n", getpid(), buf, len);
}
// 关闭使用完之后,记得关闭
close(fd[0]); // 关闭读管道
_exit(0);
}
else if (pid > 0)
{
// 父进程,写
// 关闭读通道
close(fd[0]);
// 从键盘读取数据写入到管道中
while (1)
{
char buf[32] = {""};
int len = read(0, buf, 32);
write(fd[1], buf, len);
}
// 关闭写通道
close(fd[1]);
}
return 0;
}

55
day4/pipe5.c Normal file
View File

@ -0,0 +1,55 @@
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>
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]);
for (int i = 0; i < 3; i++)
{
char buf[1024] = {};
int len = read(fd[0], buf, 1024); // 可能会阻塞,数据为空时会阻塞
buf[len - 1] = '\0';
printf("%d 父进程读取到: %s ,数据大小为 %d\n", getpid(), buf, len);
}
// 关闭使用完之后,记得关闭
close(fd[0]); // 关闭读管道
_exit(0);
}
else if (pid == 0)
{
// 子进程,写
// 关闭读通道
close(fd[0]);
// 从键盘读取数据写入到管道中
while (1)
{
char buf[32] = {""};
// int len = read(0, buf, 32);
scanf("%s", buf);
// buf[strlen(buf) - 1] = '\0';
write(fd[1], buf, strlen(buf) + 1);
}
// 关闭写通道
close(fd[1]);
}
return 0;
}