温馨提示×

C++ Linux系统调用详解

小樊
79
2025-04-08 02:25:39
栏目: 编程语言

在Linux系统中,C++程序可以通过系统调用(syscalls)与操作系统内核进行交互。系统调用是用户空间程序请求内核服务的一种机制。它们提供了一系列基本功能,如文件操作、进程控制、通信等。

以下是一些常用的Linux系统调用及其在C++中的使用方法:

1. 文件操作

  • open(): 打开一个文件。

    #include <fcntl.h>
    int fd = open("example.txt", O_RDONLY);
    if (fd == -1) {
        perror("open");
    }
    
  • read(): 从文件描述符读取数据。

    char buffer[1024];
    ssize_t bytesRead = read(fd, buffer, sizeof(buffer));
    if (bytesRead == -1) {
        perror("read");
    }
    
  • write(): 向文件描述符写入数据。

    const char* data = "Hello, World!";
    ssize_t bytesWritten = write(fd, data, strlen(data));
    if (bytesWritten == -1) {
        perror("write");
    }
    
  • close(): 关闭文件描述符。

    close(fd);
    

2. 进程控制

  • fork(): 创建一个新进程。

    pid_t pid = fork();
    if (pid == -1) {
        perror("fork");
    } else if (pid == 0) {
        // 子进程
        execl("/bin/ls", "ls", NULL);
        perror("execl");
        exit(1);
    } else {
        // 父进程
        wait(NULL);
    }
    
  • exec()系列: 执行一个新的程序。

    execl("/bin/ls", "ls", NULL);
    perror("execl");
    exit(1);
    
  • wait(): 等待子进程结束。

    pid_t pid = fork();
    if (pid == -1) {
        perror("fork");
    } else if (pid == 0) {
        // 子进程
        execl("/bin/ls", "ls", NULL);
        perror("execl");
        exit(1);
    } else {
        // 父进程
        int status;
        waitpid(pid, &status, 0);
    }
    

3. 信号处理

  • signal(): 设置信号处理函数。
    #include <csignal>
    void handler(int signum) {
        std::cout << "Received signal " << signum << std::endl;
    }
    
    int main() {
        signal(SIGINT, handler);
        while (true) {
            // 主循环
        }
        return 0;
    }
    

4. 网络编程

  • socket(): 创建一个套接字。

    #include <sys/socket.h>
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1) {
        perror("socket");
    }
    
  • bind(): 绑定套接字到地址。

    struct sockaddr_in serv_addr;
    memset(&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = INADDR_ANY;
    serv_addr.sin_port = htons(8080);
    
    if (bind(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) == -1) {
        perror("bind");
    }
    
  • listen(): 监听连接。

    if (listen(sockfd, 5) == -1) {
        perror("listen");
    }
    
  • accept(): 接受连接。

    struct sockaddr_in cli_addr;
    socklen_t clilen = sizeof(cli_addr);
    int newsockfd = accept(sockfd, (struct sockaddr*)&cli_addr, &clilen);
    if (newsockfd == -1) {
        perror("accept");
    }
    
  • connect(): 连接到服务器。

    struct sockaddr_in serv_addr;
    memset(&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(8080);
    inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr);
    
    if (connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) == -1) {
        perror("connect");
    }
    

5. 内存管理

  • mmap(): 映射文件或设备到内存。

    void* addr = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset);
    if (addr == MAP_FAILED) {
        perror("mmap");
    }
    
  • munmap(): 解除内存映射。

    if (munmap(addr, length) == -1) {
        perror("munmap");
    }
    

注意事项

  1. 错误处理: 系统调用通常返回-1表示错误,并设置errno变量。使用perror()函数可以打印错误信息。
  2. 资源管理: 确保在使用完文件描述符、套接字等资源后及时关闭或释放。
  3. 安全性: 系统调用涉及内核级别的操作,务必小心处理输入输出,避免安全漏洞。

通过这些系统调用,C++程序可以在Linux系统上实现各种复杂的功能。

0