操作系统C语言实现03---进程创建

1.介绍

进程创建是操作系统中的一项基本操作,它支持执行新程序和管理系统资源。本文将深入探讨流程创建机制,重点关注理论概念和实际实现细节。

2.概览

在这里插入图片描述

2.1 涉及的系统调用

进程创建中涉及的主要系统调用有:

  1. fork ()
    ◦通过复制调用进程创建一个新进程
    ◦子进程返回0,父进程返回子进程的PID
    ◦内核函数:do_fork()
  2. exec ()
    ◦用新程序替换当前进程映像
    ◦多个变体:execve(), execl(), execle(), execv(), execvp(), execvpe()
    ◦内核函数:do_execve()

2.2 流程创建步骤

  1. fork
    ◦重复调用过程
    ◦创建一个新的过程控制块(PCB)
    ◦为新进程分配内存
    ◦复制父的内存空间到子内存空间
  2. exec
    ◦用新程序替换子程序的内存空间
    ◦将程序加载到内存

3.Fork系统调用

3.1 详细说明

fork () 系统调用通过复制调用进程来创建一个新进程。新进程称为子进程,是父进程的精确副本,包括其内存、文件描述符和信号处理程序。唯一的区别是fork () 的返回值,在子进程中为0,而在父进程中为子进程的PID。

3.2 代码例子

一个fork () 用法的简单示例:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

int main() {
    pid_t pid;

    // Create a new process
    pid = fork();

    if (pid < 0) {
        // Fork failed
        fprintf(stderr, "Fork failed!\n");
        return 1;
    } else if (pid == 0) {
        // Child process
        printf("Child process: PID = %d\n", getpid());
        printf("Child process: Parent PID = %d\n", getppid());
        // Child process can execute a new program using exec()
    } else {
        // Parent process
        printf("Parent process: PID = %d\n", getpid());
        printf("Parent process: Child PID = %d\n", pid);
        // Wait for the child process to complete
        wait(NULL);
        printf("Parent process: Child has terminated\n");
    }

    return 0;
}

4.Exec系统调用

4.1 详细说明

exec () 系统调用用一个新程序替换当前进程映像。这通常在 fork() 之后的子进程中执行,以执行另一个程序。 exec () 函数族包括:
•execve():执行由路径名指定的程序
•execl():执行带有参数列表的程序
•execle():执行带有参数和环境变量列表的程序
•execv():执行带有参数数组的程序
•execvp():执行带有参数列表的程序,在PATH中搜索该程序
•execvpe():执行带有参数和环境变量列表的程序,在PATH中搜索该程序

4.2 代码例子

一个exec() 用法的简单示例:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

int main() {
    pid_t pid;

    // Create a new process
    pid = fork();

    if (pid < 0) {
        // Fork failed
        fprintf(stderr, "Fork failed!\n");
        return 1;
    } else if (pid == 0) {
        // Child process
        printf("Child process: PID = %d\n", getpid());
        printf("Child process: Parent PID = %d\n", getppid());
        // Execute a new program
        char *args[] = {"ls", "-l", NULL};
        execvp("ls", args);
        // If execvp returns, it must have failed
        perror("execvp");
        exit(1);
    } else {
        // Parent process
        printf("Parent process: PID = %d\n", getpid());
        printf("Parent process: Child PID = %d\n", pid);
        // Wait for the child process to complete
        wait(NULL);
        printf("Parent process: Child has terminated\n");
    }

    return 0;
}

5.在Linux内核中的进程创建

5.1 内核函数

Linux内核使用几个函数来管理进程的创建:
•do_fork():创建一个新进程
•copy_process():将父进程的状态复制到子进程
•wake_up_new_task():将新进程加入运行队列
•do_execve():加载一个新程序到当前进程

5.2 数据结构

Linux内核使用task_struct结构体来管理进程状态:

struct task_struct {
    volatile long state;    /* -1 unrunnable, 0 runnable, >0 stopped */
    void *stack;
    atomic_t usage;
    unsigned int flags;
    unsigned int ptrace;
    
    int prio, static_prio, normal_prio;
    struct list_head tasks;
    struct mm_struct *mm, *active_mm;
    
    /* ... many more fields ... */
};

6.进程创建调试

下面是一个全面的进程创建调试器:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>
#include <ctype.h>

#define MAX_PATH 1024
#define MAX_LINE 256

typedef struct {
    pid_t pid;
    char state;
    unsigned long vm_size;
    unsigned long vm_rss;
    unsigned long threads;
    char name[MAX_LINE];
} ProcessInfo;

// Function to read process information from /proc
void read_process_info(pid_t pid, ProcessInfo* info) {
    char path[MAX_PATH];
    char line[MAX_LINE];
    FILE* fp;

    // Read status file
    snprintf(path, sizeof(path), "/proc/%d/status", pid);
    fp = fopen(path, "r");
    if (!fp) return;

    info->pid = pid;
    while (fgets(line, sizeof(line), fp)) {
        if (strncmp(line, "State:", 6) == 0) {
            info->state = line[7];
        } else if (strncmp(line, "VmSize:", 7) == 0) {
            sscanf(line, "VmSize: %lu", &info->vm_size);
        } else if (strncmp(line, "VmRSS:", 6) == 0) {
            sscanf(line, "VmRSS: %lu", &info->vm_rss);
        } else if (strncmp(line, "Threads:", 8) == 0) {
            sscanf(line, "Threads: %lu", &info->threads);
        } else if (strncmp(line, "Name:", 5) == 0) {
            sscanf(line, "Name: %s", info->name);
        }
    }
    fclose(fp);
}

// Function to print process state information
void print_process_info(ProcessInfo* info) {
    printf("PID: %d\n", info->pid);
    printf("Name: %s\n", info->name);
    printf("State: %c (", info->state);
    
    switch(info->state) {
        case 'R': printf("Running"); break;
        case 'S': printf("Sleeping"); break;
        case 'D': printf("Disk Sleep"); break;
        case 'Z': printf("Zombie"); break;
        case 'T': printf("Stopped"); break;
        default: printf("Unknown");
    }
    printf(")\n");
    
    printf("Virtual Memory: %lu KB\n", info->vm_size);
    printf("RSS: %lu KB\n", info->vm_rss);
    printf("Threads: %lu\n", info->threads);
    printf("------------------------\n");
}

// Function to scan all processes
void scan_processes() {
    DIR* proc_dir;
    struct dirent* entry;
    ProcessInfo info;

    proc_dir = opendir("/proc");
    if (!proc_dir) {
        perror("Cannot open /proc");
        return;
    }

    printf("Scanning all processes...\n\n");

    while ((entry = readdir(proc_dir))) {
        // Check if the entry is a process (directory with numeric name)
        if (entry->d_type == DT_DIR) {
            char* endptr;
            pid_t pid = strtol(entry->d_name, &endptr, 10);
            if (*endptr == '\0') {  // Valid PID
                memset(&info, 0, sizeof(ProcessInfo));
                read_process_info(pid, &info);
                print_process_info(&info);
            }
        }
    }

    closedir(proc_dir);
}

int main() {
    scan_processes();
    return 0;
}

7.最佳实践

  1. 状态转换管理
    ◦始终验证状态转换
    ◦实现适当的错误处理
    ◦记录状态变化,以便调试
    ◦使用原子操作进行状态更新
  2. 资源管理
    ◦清理终止状态的资源
    ◦实现适当的信号处理
    ◦处理僵尸进程
    ◦监控资源使用情况
  3. 性能优化
    最小化上下文切换
    ◦优化流程创建
    ◦使用合适的调度策略
    ◦监控系统负载
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值