欢迎光临
我们一直在努力

Linux 进程实验如何揭示操作系统的核心秘密?

Linux 进程实验原理:探索操作系统的核心秘密

Linux 进程实验如何揭示操作系统的核心秘密?

背景与目的

在现代计算机科学中,操作系统是系统软件的基础,它负责管理和协调计算机硬件与软件资源,Linux作为一种广泛应用的开源操作系统,因其稳定性和灵活性被广泛使用,理解Linux操作系统中的进程管理机制对于深入学习操作系统原理至关重要,本文将通过一系列实验,探讨Linux系统中的进程创建、通信及调度等核心概念,旨在加深对操作系统内部工作机制的理解,明确进程与程序的区别,并掌握相关系统调用的使用。

进程控制基础

fork()系统调用

fork() 是UNIX/Linux环境下用于创建新进程的主要系统调用,格式如下:

pid_t fork(void);

返回值

对于父进程,返回子进程的PID。

对于子进程,返回0。

出错时,返回1。

fork()调用完成后,系统中存在两个几乎完全相同的进程,它们有着相同的用户级环境,但内核级环境有所不同,子进程会获得一个新的进程ID(PID)和父进程ID(PPID)。

示例代码:

#include <stdio.h>
#include <unistd.h>
int main() {
    pid_t pid = fork();
    if (pid < 0) {
        // Fork failed
        perror("fork failed");
        return 1;
    } else if (pid == 0) {
        // This is the child process
        printf("This is the child process, my PID is %d
", getpid());
    } else {
        // This is the parent process
        printf("This is the parent process, the child's PID is %d
", pid);
        wait(NULL); // Wait for the child to complete
    }
    return 0;
}

运行结果展示了父进程和子进程分别输出的信息,验证了fork()的工作原理。

exec()系统调用

exec()系列函数用于执行一个新程序,替换当前进程的地址空间,常用的有execl(),execp(),execle(),execv(),execvp(), 和execve(),以execl()为例,其格式为:

int execl(const char *path, const char *arg, ... /*, (char *) NULL */);

参数

path: 要执行的程序路径。

arg: 传递给新程序的参数列表。

最后一个参数必须用(char *) NULL

示例代码:

#include <unistd.h>
int main() {
    execl("/bin/ls", "ls", "l", (char *) NULL);
    return 0; // This will not be executed unless execl fails
}

该程序会调用/bin/ls命令列出当前目录的内容,如果execl()成功,当前进程的映像段将被新的程序替换,不会返回到原程序。

exit()系统调用

exit()用于终止进程执行,并返回一个状态码给其父进程,格式为:

void exit(int status);

参数

status: 返回给父进程的状态码。

示例代码:

#include <stdio.h>
#include <unistd.h>
int main() {
    printf("This is a process with PID %d
", getpid());
    exit(0);
}

当调用exit()后,进程会终止,并返回状态码给其父进程。

wait()系统调用

wait()使父进程挂起,直到任意一个子进程结束,格式为:

pid_t wait(int *status);

参数

Linux 进程实验如何揭示操作系统的核心秘密?

status: 存储子进程的退出状态。

返回值

成功时返回子进程的PID。

失败时返回1。

示例代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main() {
    pid_t pid = fork();
    if (pid < 0) {
        perror("fork failed");
        exit(1);
    } else if (pid == 0) {
        printf("This is the child process, my PID is %d
", getpid());
        exit(0);
    } else {
        int status;
        wait(&status); // Wait for the child to complete
        if (WIFEXITED(status)) {
            printf("Child exited with status %d
", WEXITSTATUS(status));
        }
    }
    return 0;
}

这段代码展示了父进程如何等待子进程完成并获取其退出状态。

与步骤

实验一:进程的创建与销毁

实验目的:

了解fork()系统调用的基本用法。

观察父进程和子进程之间的关系。

掌握进程的创建和终止操作。

实验步骤:

1、编写一个简单的C程序,使用fork()创建一个子进程。

2、在子进程中输出当前进程的PID和父进程的PID。

3、在父进程中等待子进程结束,并输出子进程的退出状态。

4、编译并运行程序,记录输出结果。

实验代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main() {
    pid_t pid = fork();
    if (pid < 0) {
        perror("fork failed");
        exit(1);
    } else if (pid == 0) {
        // Child process
        printf("Child process: PID = %d, PPID = %d
", getpid(), getppid());
        exit(0); // Terminate child process normally
    } else {
        // Parent process
        int status;
        waitpid(pid, &status, 0); // Wait for child to finish
        if (WIFEXITED(status)) {
            printf("Parent process: Child exited with status %d
", WEXITSTATUS(status));
        } else {
            printf("Parent process: Child terminated abnormally
");
        }
    }
    return 0;
}

预期结果:

父进程输出子进程的PID和退出状态。

子进程输出自身的PID和父进程的PID。

实验二:进程的管道通信

实验目的:

了解pipe()系统调用的基本用法。

掌握父子进程之间的管道通信机制。

熟悉管道的读写操作。

Linux 进程实验如何揭示操作系统的核心秘密?

实验步骤:

1、创建一个管道,使用pipe()系统调用。

2、使用fork()创建一个子进程。

3、父进程关闭管道的读端,子进程关闭管道的写端。

4、父进程从管道写入数据,子进程从管道读取数据。

5、编译并运行程序,记录输出结果。

实验代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
int main() {
    int pipefd[2]; // Array to hold the file descriptors for the pipe
    pid_t pid;
    char buffer[128]; // Buffer to store data read from the pipe
    const char *msg = "Hello from your parent!";
    // Create a pipe
    if (pipe(pipefd) == 1) {
        perror("pipe");
        exit(1);
    }
    // Create a child process
    pid = fork();
    if (pid == 1) {
        perror("fork");
        exit(1);
    } else if (pid == 0) {
        // Child process: close the write end of the pipe, read from the pipe
        close(pipefd[1]); // Close the write end of the pipe in the child process
        read(pipefd[0], buffer, sizeof(buffer)); // Read data from the pipe
        printf("Child process received: %s
", buffer); // Print the message received from the parent process
        close(pipefd[0]); // Close the read end of the pipe after reading is done
        exit(0); // Terminate child process normally
    } else {
        // Parent process: close the read end of the pipe, write to the pipe
        close(pipefd[0]); // Close the read end of the pipe in the parent process
        write(pipefd[1], msg, strlen(msg) + 1); // Write data to the pipe
        close(pipefd[1]); // Close the write end of the pipe after writing is done
        wait(NULL); // Wait for the child process to finish before terminating the parent process
    }
    return 0;
}

预期结果:

父进程向管道写入消息“Hello from your parent!”。

子进程从管道读取消息并打印出来。

父进程等待子进程结束后再终止。

实验三:进程的竞争与同步(选做)

实验目的:

了解进程间的竞争现象。

掌握使用信号量进行进程同步的方法。

熟悉POSIX信号量的基本操作。

实验步骤:

1、创建一个共享资源(如计数器)。

2、使用fork()创建多个子进程。

3、使用信号量确保每次只有一个子进程能访问共享资源。

4、编译并运行程序,记录输出结果。

实验代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include <semaphore.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <signal.h>
#include <time.h>
#include <string.h>
#include <stdbool.h>
#include <limits.h>
#include <bits/signum.h>
#include <bits/mman.h>
#include <bits/mqueue.h>
#include <bits/time.h>
#include <bits/resource.h>
#include <bits/select.h>
#include <bits/socket.h>
#include <bits/sendfile.h>
#include <bits/sem.h>
#include <bits/shared_coredump.h>
#include <bits/timex.h>
#include <bits/uio.h>
#include <bits/uio_prnt.h>
#include <bits/sockaddr.h>
#include <bits/sockopt.h>
#include <bits/termios.h>
#include <bits/term_ioctl.h>
#include <bits/ttycom.h>
#include <bits/ucred.h>
#include <bits/uio_prnt.h>
#include <bits/utmp.h>
#include <bits/utmp.h>
#include <bits/utmpx.h>
#include <bits/utmpx.h>
#include <bits/wchar.h>

小伙伴们,上文介绍了“Linux 进程实验原理:探索操作系统的核心秘密”的内容,你了解清楚吗?希望对你有所帮助,任何问题可以给我留言,让我们下期再见吧。

赞(0)
版权声明:本文采用知识共享 署名4.0国际许可协议 [BY-NC-SA] 进行授权
文章名称:《Linux 进程实验如何揭示操作系统的核心秘密?》
文章链接:https://yuyunkj.com/article/11306.html
本站资源仅供个人学习交流,请于下载后24小时内删除,不允许用于商业用途,否则法律问题自行承担。

评论 抢沙发