do your test before you deliver your code to community

本文详细记录了在OpenStack项目中进行测试所遇到的问题及解决方法,包括Troux的配置与使用,常见错误排查,以及依赖库安装等。通过实际案例帮助开发者高效完成测试工作。

测试是openstack中的重要一环,一个大型的项目,要想报障product的质量,没有测试只能是瞎玩,单元测试,功能测试,集成测试等等,我们这里主要说的是unittest,

也就是单元测试。早期的openstack项目里面都有runtest.sh 脚本文件,运行脚本可以生成virtual 环境,从而在不破坏现有环境下下载测试所需要的相关一类包,而CI

的流行,对于大型的openstack来说也会面临持续集成的问题,Tox的出现,作为openstack中使用的持续集成工具,使用方便而灵活。


这篇文章主要是记录,如何在openstack中进行测试所碰到的问题,解决方法等,所有会有很多链接。

早先时,使用run_test脚本进行测试的方式和tox并存,后来tox基本取代了run_test了,所以可以只关注tox,像ironic这样的新项目,干脆就只用tox了。


这是一篇不错的关于tox的链接:

http://ronaldbradford.com/blog/understanding-the-different-openstack-tox-configs-2015-04-30/

openstack测试相关的官网wiki页:

https://wiki.openstack.org/wiki/Testing

https://wiki.openstack.org/wiki/Testr

ironic使用tox测试的官方文档:

http://docs.openstack.org/developer/ironic/dev/dev-quickstart.html

测试单独一个类:

testr run ironic.tests.objects.test_port.TestPortObject.test_save

tox -epy27 -- ironic.tests.objects.test_port.TestPortObject.test_save


直接运行tox,遇到的问题:

1. tox -epy34失败,

“db type could not be determined error: testr failed (3)”

解决办法是先执行:rm .testrepository/times.dbm,再执行tox -py34,

如果run test因为超时失败,可以修改 .testr.conf文件,将timeout时间设长

2. 直接运行 tox -epep8, 用于检查code是否满足PEP8规范

3. 由于pypi的官方源不稳定,因此一开始使用 "tox -evenv--notest" 就可能会出问题,此时在 tox.ini中更改pypi源(豆瓣的源不错):

[tox]
minversion = 1.6
skipsdist = True
envlist = py34,py27,pep8
indexserver =
    default = http://pypi.douban.com/simple/

或者修改~/.pip/pip.conf文件,添加:

[global]
index-url = http://pypi.douban.com/simple
[install]
trusted-host = pypi.douban.com


以下是我碰到过的因为lib依赖出现的问题,以及安装什么库可以解决,mark一下方便查阅:

lxml失败

apt-get install libxslt1-dev libxslt1.1libxml2-dev libxml2 libssl-dev

 

psycopg2失败

apt-get install libpq-dev python-dev

 

x86_64-linux-gnu-gcc error

python-dev

如果是py34的问题,就安装python3-dev

 

libvirt error

libvirt-dev

 

[Errno 2] No such file or directory

apt-get install git

python-ldap

http://stackoverflow.com/questions/18134826/how-do-i-install-python-ldap-in-a-virtualenv-on-ubuntu

 


<think>首先,用户的问题是:“我想获取信号以传递 请问get signal to deliver”。这看起来是关于Linux内核中的信号处理,特别是“get_signal_to_deliver”函数。用户可能是在询问如何获取信号以传递给处理函数。 从系统级指令,我需要: - 所有行内数学表达式使用$...$格式。 - 独立公式使用$$...$$格式并单独成段。 - 使用中文回答。 - 生成相关问题。 - 在回答中引用的段落末尾自然地添加引用标识,例如[^1]。 用户提供了多个引用: - [^1]:描述get_signal_to_deliver函数返回值大于0时调用handle_signal函数。 - [^2]:函数的签名:int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka, struct pt_regs *regs, void *cookie)。 - [^3]:详细解释函数的行为,包括它只在CPU返回到用户态时调用,处理挂起信号等。 - [^4]:讨论SIGCONT信号和停止信号的处理。 - [^5]:一个堆栈跟踪,显示get_signal_to_deliver在信号处理流程中的位置。 用户的问题核心是“get signal to deliver”,意思是获取信号以传递。在Linux内核中,get_signal_to_deliver函数负责从挂起信号队列中获取信号,以便传递给用户空间的处理函数。 我的回答应该: 1. 解释get_signal_to_deliver函数的作用。 2. 描述其工作流程。 3. 使用中文。 4. 结构清晰,逐步解决问题。 5. 在末尾生成相关问题。 6. 在回答中引用时添加引用标识。 结构化回答: - **引言**:简要解释函数的作用。 - **详细解释**:基于引用,描述函数的行为、参数和返回值。 - **工作流程**:说明它在信号处理中的位置,如从do_signal调用。 - **关键点**:覆盖信号处理、忽略信号、默认操作等。 - **生成相关问题**:在最后添加相关问题。 确保回答真实可靠:基于提供的引用和标准Linux内核知识。 最终,添加相关问题: - 例如:如何在内核中添加自定义信号处理?get_signal_to_deliver函数的优化方法?信号处理中的竞争条件如何避免? 现在,构建回答。</think>### get_signal_to_deliver 函数详解 在 Linux 内核的信号处理机制中,`get_signal_to_deliver` 函数是一个关键的内核函数,负责从当前进程的挂起信号队列中获取信号,并准备将其传递给用户空间的信号处理函数。该函数通常在 CPU 即将返回到用户态时被调用(例如,在中断处理或系统调用返回前),以确保信号能及时被处理[^3]。以下我将逐步解释其工作原理、参数和典型行为,帮助您理解如何“获取信号以传递”。 #### 1. **函数作用与调用时机** - `get_signal_to_deliver` 的主要任务是遍历当前进程的挂起信号队列(包括 `pending` 和 `shared_pending` 队列),并选择一个合适的信号进行处理。如果信号需要传递到用户空间(例如,用户通过 `signal()` 或 `sigaction()` 设置了自定义处理函数),函数会返回该信号的详细信息[^1]。 - 调用时机:该函数仅在 CPU 准备返回到用户态时被激活,由内核检查 `TIF_SIGPENDING` 标志触发。这意味着信号处理不会在内核态中发生,而是延迟到进程即将返回用户空间时执行[^3]。 - 典型调用栈:`do_signal()` → `get_signal_to_deliver()` → `handle_signal()`。其中: - `do_signal()` 负责处理所有未阻塞的挂起信号。 - `handle_signal()` 在信号需要用户态处理时被调用,用于设置信号处理程序的执行环境(如修改硬件上下文)[^3]。 #### 2. **函数参数与返回值** 函数签名如下(基于引用[^2]): ```c int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka, struct pt_regs *regs, void *cookie) ``` - **参数说明**: - `info`:指向 `siginfo_t` 结构的指针,用于存储信号的详细信息(如信号编号、发送者 PID 等)。 - `return_ka`:指向 `struct k_sigaction` 的指针,用于返回信号的处理动作(包括用户定义的函数指针或默认行为)。 - `regs`:指向 `struct pt_regs` 的指针,包含当前进程的寄存器状态,用于在信号处理时保存和恢复上下文。 - `cookie`:一个不透明指针,通常用于内核内部扩展。 - **返回值**: - 如果返回值大于 0,表示成功获取到一个需要传递到用户空间的信号(即用户设置了自定义处理函数),此时内核会调用 `handle_signal()` 来执行后续操作[^1]。 - 如果返回值小于或等于 0,表示没有信号需要传递(例如,信号被忽略、执行默认操作,或队列为空),内核可能直接忽略信号或执行默认行为(如终止进程)[^3]。 #### 3. **工作流程详解** `get_signal_to_deliver` 函数在内部执行以下步骤: 1. **检查挂起信号队列**:反复调用 `dequeue_signal()` 函数,直到 `pending`(进程私有信号)和 `shared_pending`(线程组共享信号)队列为空。队列中的信号按优先级排序(例如,实时信号优先)[^3]。 2. **处理信号类型**: - 如果信号被忽略(例如,通过 `SIG_IGN` 设置),函数会跳过该信号。 - 如果信号需要执行默认操作(如 `SIGKILL` 终止进程),函数直接在内核态处理,不返回用户空间。 - 如果信号有用户态处理函数,函数填充 `info` 和 `return_ka` 参数,并返回正数。 3. **特殊信号处理**:对于停止信号(如 `SIGSTOP`)和继续信号(如 `SIGCONT`),函数会更新线程组状态。例如: - 当接收到 `SIGCONT` 时,如果线程组正在停止(`group_stop_count > 0`),函数会清除 `SIGNAL_STOP_DEQUEUED` 标志,确保停止过程被取消[^4]。 4. **上下文准备**:在返回用户空间前,函数通过 `setup_rt_frame()` 修改进程的硬件上下文(如栈指针),为信号处理函数的执行做好准备[^3]。 #### 4. **关键特性与注意事项** - **性能与竞争条件**:由于信号处理涉及用户态和内核态的切换,`get_signal_to_deliver` 可能成为性能瓶颈。内核通过仅在返回到用户态时调用该函数来减少开销。但竞争条件(如信号在检查队列时被添加)需要小心处理[^3]。 - **错误处理**:如果函数返回负数或 0,内核可能触发进程终止或记录错误(如内存转储),这在调试中常见(引用[^5] 展示了函数在崩溃堆栈中的位置)。 - **安全性**:函数确保信号处理不会在内核态执行,防止恶意信号导致系统崩溃。用户自定义处理函数始终在用户空间运行[^1]。 总之,`get_signal_to_deliver` 是 Linux 信号传递的核心机制,它桥接内核和用户空间,确保信号高效、安全地处理。如果您需要修改或扩展信号行为,建议查阅内核源码(如 `kernel/signal.c`)以获取更多细节。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值