c 语言进程

进程锁介绍

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

#define M 3

int tickets = 20;
pthread_mutex_t lock; //互斥锁

// 线程函数,用于售票
void *fun(void *args) {
    while (1) {
        pthread_mutex_lock(&lock); // 获取互斥锁
        if (tickets > 0) {
            sleep(1);
            tickets--;
            printf("the remaining tickets are %d\n", tickets);
        } else {
            pthread_mutex_unlock(&lock); // 释放互斥锁
            break;
        }
        pthread_mutex_unlock(&lock); // 释放互斥锁
    }
    return NULL;
}

int main() {
    pthread_t id[M];
    int i;
    pthread_mutex_init(&lock, NULL); // 初始化互斥锁
    for (i = 0; i < M; i++) {
        pthread_create(&id[i], NULL, fun, NULL);
    } //创建线程
    for (i = 0; i < M; i++) {
        pthread_join(id[i], NULL);
    } //等待线程结束
    pthread_mutex_destroy(&lock); // 销毁互斥锁
    return 0;
}


pthread_mutex_init(&lock, NULL); // 初始化互斥锁
pthread_mutex_destroy(&lock); // 销毁互斥锁
pthread_mutex_unlock(&lock); // 释放互斥锁
pthread_mutex_lock(&lock); // 获取互斥锁

进程之间的通信

  1. 普通方式
    内存映射(mmap 技术) 映射到同一物理空间
    main 函数列表 环境列表 (只对与夫进程传递给子进程)
  2. 信号 kill -sig pid 给进程发送信号
    给进程发送一个sig 信号
  3. 上古方式 pipe 管道
    4.IPC 进程间通信
    共享内存 sharemomery
    消息列列 messagequeue
    信号量集 semaphore set
    5 网络通信
    socket
socket` 是一个通信端点,它为两个网络实体之间提供了一个通信信道socket 编程是实现网络通信的一种常用方法。socket 允许程序通过网络进行数据的发送和接收,
创建 socketint sockfd = socket(AF_INET, SOCK_STREAM, 0);
AF_INET 表示使用 IPv4 地址。SOCK_STREAM 表示使用面向连接的、可靠的字节流通信(如 TCP)。
一旦创建了 socket,通常你会想要将其绑定到一个特定的网络接口和端口上
struct sockaddr_in server_addr;
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port);
server_addr.sin_addr.s_addr = INADDR_ANY;
bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
监听连对于服务器端的 socket,你需要监听传入的连接请求listen(sockfd, SOMAXCONN);
接受连接*:当服务器监听到连接请求时,它可以接受连接,从而创建一个新的 socket 用于与客户端通信。
struct sockaddr_in client_addr;
socklen_t client_len = sizeof(client_addr);
int clientfd = accept(sockfd, (struct sockaddr *)&client_addr, &client_len);
发送和接收数据:一旦建立了连接,就可以使用 sendrecv(或 writeread)函数来发送和接收数据。send(clientfd, message, strlen(message), 0); 或者 write(clientfd, message, strlen(message)); 或者 ssize_t received = recv(clientfd, buffer, sizeof(buffer) - 1, 0); 或者 ssize_t received = read(clientfd, buffer, sizeof(buffer) - 1);
数据传输完成后,应该关闭 socket 连接。close(sockfd);

在这里插入图片描述

#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
volatile sig_atomic_t running = 1; // 用于标识进程是否运行的变量

void sig_handler(int signum) { // 信号处理函数
    running = 0;
}

int main(){
    pid_t id = fork(); // 创建子进程
    if(id == -1){
        perror("fork");
        return -1; // 处理出错情况
    }
    if(id > 0){  // 在父进程中执行的代码
        return 0; // 父进程结束
    }

    printf("%d", getpid()); // 打印子进程的进程号
    setsid(); // 设置新的会话领导
    chdir("/"); // 更改进程的工作目录为根目录
    umask(0); // 设置文件创建的掩码

    int i;
    for (i=0; i<3; i++){ // 循环次数为3
        close(i); // 关闭标准输入、输出、错误流
        signal(SIGINT, sig_handler); // 如果进程收到SIGINT信号,则调用sig_handler函数
        while(running){ // 当进程运行时执行循环
            int fd = open("test.txt", O_RDWR|O_CREAT, 0666); // 打开或创建文件
            if(fd == -1){
                perror("open"); // 处理打开文件出错情况
                return -1; // 返回错误
            }
            char *p = "这是一个守护进程";
            write(fd, p, strlen(p)); // 写入数据到文件
            close(fd); // 关闭文件
            sleep(3); // 休眠3秒
        }
    }
    return 0; // 子进程结束
}

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

static void sig_usr(int);

int main(void)
{
    // 设置信号处理函数,捕获SIGUSR1信号 sig_usr是名字,函数名随意
    if (signal(SIGUSR1, sig_usr) == SIG_ERR) {
        printf("无法捕获SIGUSR1");
        exit(-1);
    }

    // 设置信号处理函数,捕获SIGUSR2信号
    if (signal(SIGUSR2, sig_usr) == SIG_ERR) {
        printf("无法捕获SIGUSR2");
        exit(-1);
    }

    // 循环等待信号
    for ( ; ; )
        pause();
}

// 信号处理函数
static void sig_usr(int signo)
{
    // 判断接收到的信号类型并作出相应处理
    if (signo == SIGUSR1) {
        printf("接收到SIGUSR1\n");
    } else if (signo == SIGUSR2) {
        printf("接收到SIGUSR2");
    } else {
        printf("接收到信号 %d\n", signo);
    }
}

无论可靠还是不可靠信号都可以sigqueue/sigacton 函数发送和安装

信号来源 硬件异常 除了 0 无效内存等

硬件异常通常被驱动检测到并通知内核
系统内核对这些信号进行进程递送相应的信号
软件异常则通过sigqueue/sigacton 函数产生信号

信号处理

可以 忽略 终止进程
终止进程产生core文件
捕获并处理 当信号发生时 内核会调用一个事先注册好的用户信号处理函数

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值