nng协议分析之互斥锁pthread_mutexattr_settype函数

此函数位于nni_plat_init ,是对线程锁的属性初始化

pthread_mutexattr_settype 是一个用于设置互斥锁属性类型的函数。通过这个函数,可以指定互斥锁的类型,以控制不同的锁定行为。

函数原型

#include <pthread.h>

int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type);


参数说明

- attr:指向互斥锁属性对象 (pthread_mutexattr_t) 的指针。
- type:互斥锁的类型。常见的类型包括:


  - PTHREAD_MUTEX_NORMAL:普通的互斥锁。当一个线程试图再次锁定一个已经锁定的互斥锁时,会发生死锁。


  - PTHREAD_MUTEX_ERRORCHECK:错误检查互斥锁。当一个线程试图再次锁定一个已经锁定的互斥锁时,会返回错误。NNG协议使用的类型就是此类型


  - PTHREAD_MUTEX_RECURSIVE:递归互斥锁。同一个线程可以多次锁定一个已经锁定的互斥锁,但必须解锁相同次数。


  - PTHREAD_MUTEX_DEFAULT:默认的互斥锁类型,通常等同于 PTHREAD_MUTEX_NORMAL。

返回值

- 0:成功。
- 非零错误码:失败。

示例代码下面是一个如何使用 pthread_mutexattr_settype 的示例:

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

void* thread_function(void* arg) {
    pthread_mutex_t* mutex = (pthread_mutex_t*)arg;

    pthread_mutex_lock(mutex);
    printf("Thread %ld: Locked the mutex.\n", pthread_self());

    // 模拟一些工作
    sleep(1);

    pthread_mutex_unlock(mutex);
    printf("Thread %ld: Unlocked the mutex.\n", pthread_self());

    return NULL;
}

int main() {
    pthread_mutexattr_t attr;
    pthread_mutex_t mutex;
    pthread_t thread;

    // 初始化互斥锁属性
    pthread_mutexattr_init(&attr);

    // 设置互斥锁类型为递归锁
    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);

    // 使用属性初始化互斥锁
    pthread_mutex_init(&mutex, &attr);

    // 创建线程
    pthread_create(&thread, NULL, thread_function, (void*)&mutex);

    // 主线程也锁定和解锁互斥锁
    pthread_mutex_lock(&mutex);
    printf("Main thread: Locked the mutex.\n");

    // 模拟一些工作
    sleep(1);

    pthread_mutex_unlock(&mutex);
    printf("Main thread: Unlocked the mutex.\n");

    // 等待线程结束
    pthread_join(thread, NULL);

    // 销毁互斥锁和属性
    pthread_mutex_destroy(&mutex);
    pthread_mutexattr_destroy(&attr);

    return 0;
}


在这个例子中,互斥锁 mutex 被配置为递归锁类型 (PTHREAD_MUTEX_RECURSIVE),这允许同一个线程多次锁定互斥锁。主线程和新创建的线程都尝试锁定和解锁互斥锁,以演示其使用。

<think>好的,用户现在问的是关于NNG_FLAG_NONBLOCK的定义和用法,需要结合之前的对话历史来回答。首先,用户之前提到了NNG的六种通信模式,引用了相关的命令示例,但这次的问题具体是关于一个特定的标志NNG_FLAG_NONBLOCK。用户还提到在nanomsg或nng库中可能有定义NNG_FLAG_NONBLOCK为2u。 首先,我需要确认这个标志的具体定义。根据之前的知识,nng库是nanomsg的继任者,所以可能需要检查nng的文档。通常,像这样的标志用于控制套接字或操作的阻塞行为。NONBLOCK标志通常用于设置非阻塞模式,这样函数调用会立即返回而不是等待操作完成。 接下来,用户给出的定义是#define NNG_FLAG_NONBLOCK 2u,这里的2u表示无符号整型2。需要验证这个值是否正确。在nng的源码中,不同的标志通常使用位掩码,比如1u、2u、4u等,每个位代表不同的选项。 然后,关于用法,这个标志可能用于各种函数,比如nng_send、nng_recv等,设置这些函数为非阻塞模式。当设置了NONBLOCK后,如果操作不能立即完成,函数会返回NNG_EAGAIN错误,而不是阻塞线程。 还需要考虑用户可能的实际应用场景,比如在高性能服务器中处理大量并发连接时,使用非阻塞模式可以避免线程被阻塞,提高响应能力。同时,可能需要结合事件循环库(如libevent,用户之前提到了event_new等函数)来处理异步I/O。 需要检查是否有官方文档或头文件中的定义支持这个值,并举例说明如何在代码中使用这个标志。比如在调用nng_send时传递NNG_FLAG_NONBLOCK作为参数中的标志位,并处理可能的错误情况。 此外,用户可能想知道这个标志与其他标志的区别,比如是否与其他标志位有组合使用的情况,或者在不同函数中的行为差异。例如,在nng_send和nng_recv中使用NONBLOCK的效果是否一致。 还要注意用户之前的问题中提到的event_new函数中的事件标志,如EV_READ、EV_WRITE等,可能与NNG的非阻塞I/O结合使用,实现异步网络通信。这时候可能需要解释如何将NNG的非阻塞操作与事件循环集成,例如在数据可读或可写时触发回调函数,而不是阻塞等待。 最后,确保回答结构清晰,分点解释定义、用法、示例和注意事项,并引用相关的资料,如官方文档或源码中的定义。同时,生成的相关问题需要围绕NNG的其他标志、错误处理、性能影响等方面展开,帮助用户进一步理解。</think>### **NNG_FLAG_NONBLOCK 详解** #### **1. 定义与作用** `NNG_FLAG_NONBLOCK` 是 **NNG(Nanomsg Next Generation)库** 中的一个标志宏,用于指定套接字操作(如发送或接收)的 **非阻塞模式**。其核心目的是避免函数在无法立即完成操作时阻塞当前线程,而是直接返回错误码 `NNG_EAGAIN`,从而支持异步或高并发场景的高效处理。 - **宏定义**(根据NNG源码[^1]): ```c #define NNG_FLAG_NONBLOCK 2u ``` 其中 `2u` 表示无符号整数 `2`,对应二进制位掩码中的第二位。 (注:不同版本库中该值可能变动,建议通过头文件验证) --- #### **2. 使用场景** 此标志主要用于以下函数(部分示例): - **发送消息**:`nng_send()` - **接收消息**:`nng_recv()` - **连接建立**:`nng_dial()` / `nng_listen()` **作用**: - 当操作无法立即完成时,函数立即返回 `NNG_EAGAIN`,而非等待资源就绪。 - 适用于事件驱动架构(如结合 `libevent`),配合回调机制实现异步I/O[^1]。 --- #### **3. 代码示例** ```c #include <nng/nng.h> #include <nng/protocol/pipeline0/push.h> nng_socket socket; int rv; // 创建PUSH套接字 rv = nng_push0_open(&socket); if (rv != 0) { /* 错误处理 */ } // 发送消息(非阻塞模式) char *msg = "Hello"; size_t len = strlen(msg) + 1; rv = nng_send(socket, msg, len, NNG_FLAG_NONBLOCK); if (rv == NNG_EAGAIN) { // 发送缓冲区已满,需等待可写事件 // 可注册到事件循环(如event_add())[^1] } else if (rv != 0) { // 其他错误处理 } ``` --- #### **4. 关键行为对比** | **操作模式** | **行为** | **返回值** | |--------------------|-------------------------------------------|---------------------| | **阻塞模式** | 等待直到操作完成或超时 | `0`(成功)或错误码 | | **非阻塞模式** | 立即返回,不等待 | `0` 或 `NNG_EAGAIN` | --- #### **5. 注意事项** 1. **错误处理**: 非阻塞模式下需显式处理 `NNG_EAGAIN`,通常需结合事件通知机制(如 `poll`、`epoll` 或 `libevent`)重试操作。 ```c // 示例:注册可写事件回调 event_add(write_event, &tv); // 参考event_new()[^1] ``` 2. **性能影响**: 频繁返回 `NNG_EAGAIN` 可能增加CPU负载,需合理设计重试策略或调整缓冲区大小。 3. **与其他标志组合**: `NNG_FLAG_NONBLOCK` 可与其他标志(如 `NNG_FLAG_ALLOC`)按位或组合使用: ```c nng_recv(socket, &buf, &len, NNG_FLAG_NONBLOCK | NNG_FLAG_ALLOC); ``` --- ### **相关问题** 1. 如何通过NNG实现超时控制(如 `NNG_FLAG_TIMEOUT`)? 2. NNG中如何处理 `NNG_EAGAIN` 以外的错误类型? 3. 非阻塞模式与异步回调机制如何协作提升并发性能? --- **引用说明** [^1]: `event_new()` 用于创建事件监听,可与NNG非阻塞操作结合实现异步I/O。 [^2]: NNG的通信模式(如Pipeline)需根据协议类型配置套接字。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值