学校里开设的稍微有点用的一节课,所有代码均在ubuntu20.04下测试成功。

文件操作

1、利用creat()、open()和close()函数进行系统调用,实现创建、打开和关闭一个文件。 (1)以可读写方式新建并关闭一个文件“stu.txt”,如果成功则返回新建文件的文 件名,不成功则输出错误提示信息。 (2) 以可读写方式打开并关闭一个文件“file.txt”,如果成功则返回文件的文件名, 不成功则输出错误提示信息。

 1#include <sys/stat.h>
 2#include <fcntl.h>
 3#include <unistd.h>
 4#include <stdio.h>
 5
 6int main()
 7{
 8	const char *stufilename = "stu.txt";
 9	int stufd = creat(stufilename, S_IRWXG);
10	if (stufd == -1)
11	{
12		printf("%s creat failed\n", stufilename);
13	}
14	close(stufd);
15
16	const char *filename = "file.txt";
17	int filefd = open(filename, O_RDWR | O_CREAT | O_TRUNC, 0777);
18	if (filefd == -1)
19	{
20		printf("%s open failed!\n", filename);
21	}
22
23	return 0;
24}

2、编程实现一个简单的学生信息管理程序: (1)从键盘输入3个学生信息(学号、姓名、年龄),存放于结构体数组中,将结 构体写入文件“stu.txt”中。 (2)从键盘输入某个学生的学号,从“stu.txt”文件中读出指定学号的学生的全部 信息并显示。 (3) 实现人机交互操作:可以循环查询并显示查询结果,直到用户不再操作,结 束程序运行。

  1#include <fcntl.h>
  2#include <unistd.h>
  3#include <stdio.h>
  4#include <stdbool.h>
  5
  6typedef struct
  7{
  8    int id;
  9    char name[50];
 10    int age;
 11} Student;
 12
 13const char *StuFileName = "./stu.txt";
 14
 15int inputStudents(int fd, int count);
 16int searchStudent(int fd, int id, int count);
 17
 18int main()
 19{
 20    int stufd = open(StuFileName, O_RDWR | O_CREAT | O_TRUNC, 0777);
 21    if (stufd == -1)
 22    {
 23        printf("%s creat failed\n", StuFileName);
 24        return 0;
 25    }
 26
 27    int inre = inputStudents(stufd, 3);
 28    if (inre == -1)
 29    {
 30        printf("写入失败\n");
 31    }
 32
 33    while (true)
 34    {
 35        int id;
 36        printf("请输入要查找的学生id(输入-1退出):");
 37        scanf("%d", &id);
 38        if (id == -1)
 39            break;
 40
 41        int sere = searchStudent(stufd, id, 3);
 42        if (inre == -1)
 43        {
 44            printf("查找失败\n");
 45        }
 46    }
 47
 48    close(stufd);
 49
 50    return 0;
 51}
 52
 53int inputStudents(int fd, int count)
 54{
 55    Student student;
 56    for (int i = 0; i < count; i++)
 57    {
 58        printf("输入第 %d 个学生的信息:\n", i + 1);
 59        printf("学号:");
 60        scanf("%d", &student.id);
 61        printf("姓名:");
 62        scanf("%s", student.name);
 63        printf("年龄:");
 64        scanf("%d", &student.age);
 65
 66        off_t fdof = lseek(fd, i * sizeof(student), SEEK_SET);
 67        if (fdof == -1)
 68            return -1;
 69
 70        if (write(fd, &student, sizeof(student)) == -1)
 71        {
 72            printf("write err\n");
 73            return -1;
 74        }
 75    }
 76
 77    off_t fdof = lseek(fd, 0, SEEK_SET);
 78    if (fdof == -1)
 79        return -1;
 80
 81    return 0;
 82}
 83
 84int searchStudent(int fd, int id, int count)
 85{
 86    Student student;
 87    for (int i = 0; i < count; i++)
 88    {
 89        off_t fdof = lseek(fd, i * sizeof(student), SEEK_SET);
 90        if (fdof == -1)
 91            return -1;
 92        if (read(fd, &student, sizeof(student)) == -1)
 93        {
 94            printf("read err\n");
 95            return -1;
 96        }
 97
 98        if (student.id == id)
 99        {
100            printf("查找到:\n");
101            printf("姓名:%s\n", student.name);
102            printf("年龄:%d\n", student.age);
103        }
104    }
105
106    if (student.id != id) {
107        printf("未查找到!\n");
108    }
109
110    off_t fdof = lseek(fd, 0, SEEK_SET);
111    if (fdof == -1)
112        return -1;
113
114    return 0;
115}

进程创建

1、使用fork()函数循环创建n个子进程(n≥2),并显示每个子进程的进程号以 及其父进程的进程号。

 1#include <stdio.h>
 2#include <stdlib.h>
 3#include <unistd.h>
 4#include <fcntl.h>
 5#include <sys/wait.h>
 6
 7void create_processes(int n)
 8{
 9    for (int i = 0; i < n; i++)
10    {
11        pid_t pid = fork();
12        if (pid < 0)
13        {
14            printf("进程创建失败");
15            exit(1);
16        }
17        else if (pid == 0)
18        {
19            printf("创建成功,子进程 PID: %d, 父进程 PID: %d\n", getpid(), getppid());
20            exit(0);
21        }
22    }
23
24    for (int i = 0; i < n; i++)
25    {
26        wait(NULL);
27    }
28}
29
30int main()
31{
32    int n = 0;
33    printf("需要创建进程的数量:");
34    scanf("%d", &n);
35    create_processes(n);
36    return 0;
37}

2、使用fork()函数创建一个子进程,在子进程中使用execl()函数执行ls命令 (ls命令的参数自定),并在屏幕上显示“任务完成!”提示。

 1#include <stdio.h>
 2#include <stdlib.h>
 3#include <unistd.h>
 4#include <fcntl.h> 
 5#include <sys/wait.h>
 6#include<sys/types.h>
 7#include<stdbool.h>
 8
 9void create_processes(int n)
10{
11    for (int i = 0; i < n; i++)
12    {
13        pid_t pid = fork();
14        if (pid < 0)
15        {
16            printf("进程创建失败");
17            exit(1);
18        }
19        else if (pid == 0)
20        {
21            printf("子进程%d,开始执行ls -l\n", getpid());
22            execl("/bin/ls", "ls", "-l", NULL);
23            exit(0);
24        }
25        int status = 0;
26
27        waitpid(pid, &status, 0);
28        bool a = WIFEXITED(status);
29        if (a) {
30            printf("子进程%d,执行ls -l成功\n", pid);
31        }
32    }
33
34    for (int i = 0; i < n; i++)
35    {
36        wait(NULL);
37    }
38}
39
40int main()
41{
42    int n = 0;
43    printf("需要创建进程的数量:");
44    scanf("%d", &n);
45    create_processes(n);
46    return 0;
47}

3、使用system()函数顺序执行以上两个可执行程序。

1#include <stdio.h>
2#include <stdlib.h>
3
4int main() {
5    system("./create_process");
6    system("./execute_ls");
7    return 0;
8}

进程间通信

1、在主程序中用pipe()创建一个管道,用fork()创建一个子进程,其父进程接收 从键盘输入一个字符串,并写入管道中;子进程从管道中读取该字符串,显示信息如下: ①统计字符串中字符的个数,并显示; ②显示字符串内容。

 1#include<stdio.h>
 2#include<string.h>
 3#include<unistd.h>
 4#include<sys/types.h>
 5
 6#define ERR -1
 7
 8int main(void)
 9{
10    int res = ERR;
11    int fd[2], nbytes;
12
13    int *write_fd = &fd[1];
14    int *read_fd = &fd[0];
15
16    res = pipe(fd);
17
18    if (res == ERR)
19    {
20        printf("创建管道失败!");
21        return ERR;
22    }
23
24    pid_t pid = fork();
25
26    if (pid == ERR)
27    {
28        printf("创建子进程失败!");
29        return -1;
30    }
31
32    if (pid == 0)
33    {
34        close(*read_fd);
35        char string[100];
36        printf("向子进程写入:");
37        scanf("%s", string);
38        write(*write_fd, string, strlen(string));
39    }
40    else
41    {
42        close(*write_fd);
43        char readbufffer[100];
44        ssize_t num = read(*read_fd, readbufffer, sizeof(readbufffer));
45        printf("子进程(pid=%d),接收到%ld字节数据: %s\n", pid, num, readbufffer);
46    }
47
48    return 0;
49}

2、编写两个程序,程序1接收到SIGUSR1信号时显示一行信息:“sigusr1 signal received!”,程序2每隔2秒钟发送一个SIGUSR1信号给程序1。 注意:该题由两个程序组成,需要在两个窗口分别运行。运行顺序:首先运行程序1,因为在程序1中需要编写接收SIGUSR1信号函数,并得到父进程ID;然后运行程序2,程序2的作用是接收到程序1中父进程的ID后,确认发送信息对象,然后每隔2秒钟发送一个SIGUSR1信号给程序1中的父进程。 程序运行用Ctrl+C结束。

 1#include <stdio.h>
 2#include <unistd.h>
 3#include <signal.h>
 4#include <stdbool.h>
 5
 6void handler(int signum)
 7{
 8    printf("接收到SIGUSR1\n");
 9    return;
10}
11
12int main(void)
13{
14    printf("我的PID是%d\n", getpid());
15    signal(SIGUSR1, handler);
16
17    while (true)
18        ;
19
20    return 0;
21}
 1#include <stdio.h>
 2#include <stdlib.h>
 3#include <signal.h>
 4#include <unistd.h>
 5#include <sys/types.h>
 6
 7#define ERR -1
 8
 9int main() {
10    pid_t pid;
11
12    printf("输入程序1的PID:");
13    scanf("%d", &pid);
14
15    while (1) {
16        if (kill(pid, SIGUSR1) == ERR) {
17            perror("发送信号失败\n");
18            return -1;
19        }
20        printf("发送成功\n");
21        sleep(2);
22    }
23
24    return 0;
25}

3、设计一个程序:要求主程序运行时,即使用户按下Ctrl+C键也不能影响正在运行的程序,即让信号处于阻塞状态;当主程序运行完毕后才进入自定义信号处理函数执行。要求: (1)主程序:每2秒钟输出提示“当前程序处于信号阻塞状态!”,循环显示5次 (2)自定义信号处理函数:查看当前路径下的所有文件信息。

 1#include <stdio.h>
 2#include <stdlib.h>
 3#include <unistd.h>
 4#include <signal.h>
 5#include <dirent.h>
 6#include <stdbool.h>
 7#include <sys/types.h>
 8
 9#define ERR -1
10
11void handler(int signum)
12{
13    printf("接收到SIGINT\n");
14    execl("/bin/ls", "ls", "-l", NULL);
15    return;
16}
17
18int main(void)
19{
20    sigset_t set;
21    sigemptyset(&set);
22
23    sigaddset(&set, SIGINT);
24
25    if (sigprocmask(SIG_BLOCK, &set, NULL) == ERR)
26    {
27        printf("屏蔽SIGINT信号失败");
28        return -1;
29    }
30
31    signal(SIGINT, handler);
32
33    for (int i = 0; i < 5; i++)
34    {
35        printf("当前程序处于阻塞状态!\n");
36        sleep(2);
37    }
38
39    if (sigprocmask(SIG_UNBLOCK, &set, NULL) == ERR)
40    {
41        printf("解除信号屏蔽失败!\n");
42        return -1;
43    }
44    printf("解除信号屏蔽成功!\n");
45
46    while (true)
47    {
48        pause();
49    }
50
51    return 0;
52}