📜  UnixLinux 中的进程控制命令(1)

📅  最后修改于: 2023-12-03 14:48:13.658000             🧑  作者: Mango

Unix/Linux 中的进程控制命令

在 Unix/Linux 操作系统中,进程控制是一个非常重要的任务。进程控制命令允许程序员管理和操作正在运行的进程,包括查看进程列表、启动新进程、停止或终止进程等。本文将介绍一些常用的进程控制命令。

进程列表和状态
ps

ps 命令用于列出当前系统中运行的进程。以下命令将显示进程的 PID(进程标识符)、PPID(父进程标识符)、CPU 占用、内存占用以及进程状态等信息。

ps aux
top

top 命令以实时交互方式显示系统的进程状况。它可以按照 CPU 使用率或内存占用等指标进行排序,并可以动态更新显示结果。

top
进程创建和管理
fork

fork() 系统调用用于创建一个新进程,该新进程是原始进程的副本。新进程将继承原始进程的代码、数据和文件描述符等属性。以下是一个使用 fork() 创建子进程的示例:

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

int main() {
    pid_t pid;
    pid = fork();
    
    if (pid == 0) {
        // 子进程
        printf("Child process\n");
    } else if (pid > 0) {
        // 父进程
        printf("Parent process\n");
    } else {
        // 创建进程失败
        fprintf(stderr, "Fork failed\n");
        return 1;
    }
    return 0;
}
exec

exec 系列函数用于在当前进程中执行新的程序。它会用指定的可执行文件替换当前进程的代码段、数据段和堆栈等属性。以下是 execvp() 函数的一个示例:

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

int main() {
    char *binaryPath = "/bin/ls";
    char *args[] = {"ls", "-l", NULL};
    
    execvp(binaryPath, args);
    
    // execvp() 函数只在执行失败时才返回,所以如果执行到这里表示出错了
    fprintf(stderr, "Execution failed\n");
    return 1;
}
kill

kill 命令用于向指定的进程发送信号。一个常用的信号是 SIGKILL,用于强制终止进程。以下命令将向进程号为 PID 的进程发送 SIGKILL 信号:

kill -9 PID
pkill

pkill 命令用于根据进程名或其他属性向进程发送信号。以下命令将向名为 process_name 的进程发送 SIGKILL 信号:

pkill -9 process_name
进程状态和控制
ps

ps 命令还可以用于查看进程的状态信息。以下命令使用 ps 查看所有进程的运行状态:

ps -ef
renice

renice 命令用于修改进程的优先级。以下命令将进程号为 PID 的进程的优先级调整为 NICE

renice NICE PID
nice

nice 命令可以在运行新程序时为其指定优先级。以下命令将运行 command 并将其优先级设置为 NICE

nice -n NICE command
进程通信
pipe

pipe 系统调用用于创建一个管道,可用于父子进程或者兄弟进程之间进行通信。以下是一个用于父子进程通信的例子:

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define BUFFER_SIZE 25

int main() {
    int pipefd[2];
    pid_t pid;
    char message[BUFFER_SIZE] = "Hello, pipe!";
    
    if (pipe(pipefd) == -1) {
        fprintf(stderr, "Pipe failed\n");
        return 1;
    }
    
    pid = fork();
    
    if (pid == 0) {
        // 子进程
        close(pipefd[1]); // 关闭写端
        
        // 从管道中读取消息
        read(pipefd[0], message, BUFFER_SIZE);
        printf("Child received: %s\n", message);
        close(pipefd[0]);
    } else if (pid > 0) {
        // 父进程
        close(pipefd[0]); // 关闭读端
        
        // 向管道中写入消息
        write(pipefd[1], message, strlen(message) + 1);
        close(pipefd[1]);
    } else {
        // 创建进程失败
        fprintf(stderr, "Fork failed\n");
        return 1;
    }
    return 0;
}
socket

socket 系统调用用于创建一个网络套接字,可用于不同计算机上的进程之间进行通信。通过套接字,进程可以进行双向的数据传输。以下是一个简单的使用套接字进行通信的例子:

#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>

#define MAX_BUFFER_SIZE 1024
#define PORT 8080

int main() {
    int serverSocket, newSocket;
    struct sockaddr_in serverAddress, clientAddress;
    int addressLength = sizeof(serverAddress);
    char buffer[MAX_BUFFER_SIZE] = {0};
    
    if ((serverSocket = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
        perror("Socket creation failed");
        exit(EXIT_FAILURE);
    }
    
    serverAddress.sin_family = AF_INET;
    serverAddress.sin_addr.s_addr = INADDR_ANY;
    serverAddress.sin_port = htons(PORT);
    
    if (bind(serverSocket, (struct sockaddr *)&serverAddress, sizeof(serverAddress)) < 0) {
        perror("Bind failed");
        exit(EXIT_FAILURE);
    }
    
    if (listen(serverSocket, 3) < 0) {
        perror("Listen failed");
        exit(EXIT_FAILURE);
    }
    
    if ((newSocket = accept(serverSocket, (struct sockaddr *)&serverAddress, (socklen_t*)&addressLength)) < 0) {
        perror("Accept failed");
        exit(EXIT_FAILURE);
    }
    
    read(newSocket, buffer, MAX_BUFFER_SIZE);
    printf("Received message: %s\n", buffer);
    
    close(newSocket);
    close(serverSocket);
    
    return 0;
}
总结

本文介绍了在 Unix/Linux 中的一些常用进程控制命令,包括进程列表和状态、进程创建和管理、进程状态和控制以及进程通信等方面的内容。熟练使用这些命令能够提高程序员在 Unix/Linux 环境下的工作效率。请记得根据实际需求和情况选择适当的命令进行使用。