开启进程俩种方式

#!/usr/bin/env python
# encoding: utf-8  
# Date: 2018/6/16


# # 方式一:
# from multiprocessing import Process
# import time
#
#
# # 定义task,开启进程就是执行任务
# def task(name):
#     print('%s is running' % name)
#     time.sleep(3)
#     print('%s is done' % name)
#
#
# if __name__ == '__main__':
#     # Process(target=task, kwargs={'name': '子进程1'})  # 传参数方式,一般使用下面一种
#     p = Process(target=task, args=('子进程1',))  # target=task()加括号代表立刻执行
#     p.start()  # 仅仅只是给操作系统发送了一个信号
#
#     print('主')
#
# # 主
# # 子进程1 is running
# # 子进程1 is done

# 方式二
from multiprocessing import Process
import time


class MyProcess(Process):
    def __init__(self, name):
        super().__init__()
        self.name = name

    def run(self):  # 自己定义的类名称必须是run ,不能使用start
        print('%s is running' % self.name)
        time.sleep(3)
        print('%s is done' % self.name)


if __name__ == '__main__':
    p = MyProcess('子进程1')
    p.start()  # 调用的是类中的run

# 子进程1 is running
# 子进程1 is done

转载于:https://www.cnblogs.com/fmgao-technology/p/9191319.html

<think>好的,我需要回答用户的问题:“所以之前程序的问题是我创建的信号量没在两个进程间共享么?” 首先,回顾之前的程序,用户使用了命名信号量(通过`sem_open`创建),理论上应该可以在进程间共享。但用户怀疑信号量没有正确共享,导致同步问题。 我需要检查程序中的信号量创建和使用部分。程序中,父进程创建了信号量: ```c stats->sem_send = sem_open(SEM_SEND, O_CREAT | O_EXCL, 0666, 0); stats->sem_recv = sem_open(SEM_RECV, O_CREAT | O_EXCL, 0666, 0); ``` 这里使用了`O_CREAT | O_EXCL`标志,确保信号量是新创建的。子进程在循环中使用`sem_wait`等待信号量。但问题可能出在信号量的创建方式是否正确,或者是否在两个进程中正确打开。 可能的问题点: 1. **信号量名称是否一致**:确保父进程和子进程使用相同的名称(SEM_SEND和SEM_RECV)。 2. **信号量权限设置**:检查权限是否正确,允许读写。 3. **信号量是否正确初始化**:初始值为0,父进程发送时post,子进程等待,这可能导致死锁? 4. **错误处理缺失**:如果`sem_open`失败,程序可能没有检查,导致后续操作无效信号量。 另外,用户可能在运行时遇到同步问题,例如子进程无法正确等待到信号量,导致数据丢失或死锁。需要确认信号量是否确实被共享,并且在两个进程中正确使用。 可能的解决方案包括检查信号量创建是否成功,确保名称正确,权限设置正确,以及同步逻辑是否合理,例如父进程先post,子进程后wait,或者是否存在初始状态导致的阻塞。</think>### 信号量共享问题分析及解决方案 在你的程序中,信号量 **确实实现了跨进程共享**,但存在 **使用方式不当** 的问题,导致同步失败。以下是详细分析: --- #### 一、信号量创建与共享机制验证 1. **命名信号量的共享性** - 通过 `sem_open` 创建的命名信号量(如 `SEM_SEND` 和 `SEM_RECV`)**天生支持进程间共享** - 核心代码: ```c stats->sem_send = sem_open(SEM_SEND, O_CREAT | O_EXCL, 0666, 0); stats->sem_recv = sem_open(SEM_RECV, O_CREAT | O_EXCL, 0666, 0); ``` - 验证方法: ```bash ls -l /dev/shm/ | grep ipc_sem # 应能看到 ipc_sem_send 和 ipc_sem_recv ``` 2. **信号量共享性测试** ```c // 在子进程中添加验证代码 printf("B 进程: sem_send=%p\n", stats->sem_send); printf("B 进程: sem_recv=%p\n", stats->sem_recv); ``` - **预期结果**:父子进程打印的地址值应相同(因共享内存映射) --- #### 二、同步失败的根本原因 1. **信号量初始值设置不当** - **问题代码**: ```c sem_open(SEM_SEND, O_CREAT | O_EXCL, 0666, 0); // 初始值为0 ``` - **导致的问题**: - 子进程执行 `sem_wait(stats->sem_send)` 时会 **立即阻塞** - 父进程在首次发送前未调用 `sem_post`,导致 **死锁** 2. **同步逻辑设计缺陷** - **错误流程**: ```mermaid sequenceDiagram A->>B: 无初始信号 B->>B: sem_wait(sem_send) // 永久阻塞 A->>A: 发送数据 A->>B: sem_post(sem_send) // 此时B已阻塞,无法响应 ``` 3. **缺少错误检查** - **关键缺失**: ```c // 应检查信号量创建结果 if (stats->sem_send == SEM_FAILED || stats->sem_recv == SEM_FAILED) { perror("信号量创建失败"); exit(1); } ``` --- #### 三、修复方案 1. **调整信号量初始值** - **修改后的创建逻辑**: ```c // 父进程先允许子进程等待 stats->sem_send = sem_open(SEM_SEND, O_CREAT | O_EXCL, 0666, 0); stats->sem_recv = sem_open(SEM_RECV, O_CREAT | O_EXCL, 0666, 1); // 初始值为1 ``` - **解释**: - `sem_recv` 初始值设为1,允许父进程首次发送时不阻塞 2. **初始化同步握手** ```c // 父进程创建子进程后 if (pid != 0) { // 等待子进程初始化完成 sleep(1); // 简单等待,实际应使用信号量握手 } ``` 3. **优化同步流程** ```mermaid sequenceDiagram A->>B: fork创建子进程 B->>B: sem_wait(sem_recv) // 初始值为1,立即通过 A->>A: 发送初始信号 A->>B: sem_post(sem_send) B->>B: sem_wait(sem_send) // 接收到信号 ``` 4. **添加错误处理** ```c // 在信号量创建后添加 if (stats->sem_send == SEM_FAILED || stats->sem_recv == SEM_FAILED) { fprintf(stderr, "信号量创建失败: %s\n", strerror(errno)); exit(EXIT_FAILURE); } ``` --- #### 四、验证修复效果 1. **添加调试输出** ```c // 在子进程循环开始时 printf("[%s] B: 开始等待数据...\n", get_time_str()); // 在父进程发送数据前 printf("[%s] A: 准备发送数据\n", get_time_str()); ``` 2. **预期输出结果** ```bash [14:30:00] A: 准备发送数据 [14:30:00] B: 开始等待数据... [14:30:00] B: 接收了 45 字节数据 校验成功 [14:30:00] A: B 告知接收 成功 ``` 3. **使用系统工具验证** ```bash ipcs -s # 查看信号量状态 # 输出示例: # key semid owner perms nsems # 0x00000000 123456 user 666 1 ``` --- #### 五、完整修复代码片段 ```c // 修复后的信号量初始化 stats->sem_send = sem_open(SEM_SEND, O_CREAT | O_EXCL, 0666, 0); stats->sem_recv = sem_open(SEM_RECV, O_CREAT | O_EXCL, 0666, 1); // 初始值为1 // 错误检查 if (stats->sem_send == SEM_FAILED || stats->sem_recv == SEM_FAILED) { fprintf(stderr, "信号量创建失败: %s\n", strerror(errno)); exit(EXIT_FAILURE); } // 父进程发送逻辑改进 write(pipefd[1], &data_len, sizeof(int)); // 发送数据长度 sem_post(stats->sem_send); // 先通知子进程 read(pipefd[0], &ack, sizeof(int)); // 再等待应答 // 子进程接收逻辑改进 sem_wait(stats->sem_send); // 等待通知 read(pipefd[0], &data_len, sizeof(int)); // 读取数据长度 sem_post(stats->sem_recv); // 发送应答 ``` --- ### 总结 | 问题类型 | 原因分析 | 解决方案 | |----------------|------------------------------|----------------------------------| | 信号量共享 | 信号量已正确共享 | 无需修改 | | 同步逻辑错误 | 初始值设置不当导致死锁 | 调整初始值,添加初始化等待 | | 错误处理缺失 | 未检查信号量创建结果 | 添加错误检查代码 | | 资源竞争风险 | 缺乏握手机制 | 使用信号量或管道进行初始化同步 | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值