`
wqtn22
  • 浏览: 101550 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

erlang NIF部分接口实现(五)复用driver功能的接口

    博客分类:
  • erts
 
阅读更多

NIF除了自身提供的功能外,还封装了一系列driver的功能,这些功能与操作系统平台紧密相关,主要包括:

系统信息, 操作系统线程及线程私有资源 ,条件变量、信号量、读写锁等,这些功能本身与erlang的进程体系无关,本身也是线程安全的,因此可以直接复用到NIF中,统一NIF的接口。

此处简单的分析一个操作系统线程创建的接口,其余的类似。

int enif_thread_create(char *name, ErlNifTid *tid, void* (*func)(void *),

      void *args, ErlNifThreadOpts *opts) {

    return erl_drv_thread_create(name,tid,func,args,(ErlDrvThreadOpts*)opts);

}

enif_thread_create直接调用了对应的driver接口erl_drv_thread_create,其它复用driver功能的接口也类似。

int

erl_drv_thread_create(char *name,

     ErlDrvTid *tid,

     void* (*func)(void*),

     void* arg,

     ErlDrvThreadOpts *opts)

{

#ifdef USE_THREADS

    int res;

    struct ErlDrvTid_ *dtid;

    ethr_thr_opts ethr_opts;

    ethr_thr_opts *use_opts;

 

    if (!opts)

use_opts = NULL;

    else {

sys_memcpy((void *) &ethr_opts,

  (void *) &def_ethr_opts,

  sizeof(ethr_thr_opts));

ethr_opts.suggested_stack_size = opts->suggested_stack_size;

use_opts = &ethr_opts;

    }


    dtid = erts_alloc_fnf(ERTS_ALC_T_DRV_TID,

 (sizeof(struct ErlDrvTid_)

  + (name ? sys_strlen(name) + 1 : 0)));

    /* 分配一个ErlDrvTid_结构,保存线程描述符 */

    /*

        struct ErlDrvTid_ {

            ethr_tid tid;

            void* (*func)(void*);

            void* arg;

            int drv_thr;

            Uint tsd_len;

            void **tsd;

            char *name;

        };

     */

 

    if (!dtid)

return ENOMEM;

 

    dtid->drv_thr = 1;

    dtid->func = func;

    dtid->arg = arg;

    dtid->tsd = NULL;

    dtid->tsd_len = 0;


    /* 填充线程描述符,func为线程执行入口点,arg为其参数,tsd为线程私有数据结构,可以保存线程私有数据,与线程紧密相关 */

 

    if (!name)

dtid->name = no_name;

    else {

dtid->name = ((char *) dtid) + sizeof(struct ErlDrvTid_);

sys_strcpy(dtid->name, name);

    }

    res = ethr_thr_create(&dtid->tid, erl_drv_thread_wrapper, dtid, use_opts);


    /* 创建一个操作系统线程,该线程并不直接以用户提供的函数为入口点,而是提供了一层外覆函数, 外覆 函数为erl_drv_thread_wrapper */

 

    if (res != 0) {

erts_free(ERTS_ALC_T_DRV_TID, dtid);

return res;

    }

 

    *tid = (ErlDrvTid) dtid;


    /* 返回创建的线程描述符 */

 

    return 0;

#else

    return ENOTSUP;

#endif

}

int ethr_thr_create(ethr_tid *tid, void * (*func)(void *), void *arg, ethr_thr_opts *opts)

{

    ethr_thr_wrap_data__ twd;

    pthread_attr_t attr;

    int res, dres;

    int use_stack_size = (opts && opts->suggested_stack_size >= 0

 ? opts->suggested_stack_size

 : -1 /* Use system default */);

 

#ifdef ETHR_MODIFIED_DEFAULT_STACK_SIZE

    if (use_stack_size < 0)

use_stack_size = ETHR_MODIFIED_DEFAULT_STACK_SIZE;

#endif

 

#if ETHR_XCHK

    if (ethr_not_completely_inited__) {

ETHR_ASSERT(0);

return EACCES;

    }

    if (!tid || !func) {

ETHR_ASSERT(0);

return EINVAL;

    }

#endif

 

    ethr_atomic32_init(&twd.result, (ethr_sint32_t) -1);

    twd.tse = ethr_get_ts_event();

    twd.thr_func = func;

    twd.arg = arg;

 

    res = pthread_attr_init(&attr);

    if (res != 0)

return res;

 

    /* Error cleanup needed after this point */

 

    /* Schedule child thread in system scope (if possible) ... */

    res = pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);

    if (res != 0 && res != ENOTSUP)

goto error;

 

    if (use_stack_size >= 0) {

size_t suggested_stack_size = (size_t) use_stack_size;

size_t stack_size;

#ifdef ETHR_DEBUG

suggested_stack_size /= 2; /* Make sure we got margin */

#endif

#ifdef ETHR_STACK_GUARD_SIZE

/* The guard is at least on some platforms included in the stack size

  passed when creating threads */

suggested_stack_size += ETHR_B2KW(ETHR_STACK_GUARD_SIZE);

#endif

if (suggested_stack_size < ethr_min_stack_size__)

   stack_size = ETHR_KW2B(ethr_min_stack_size__);

else if (suggested_stack_size > ethr_max_stack_size__)

   stack_size = ETHR_KW2B(ethr_max_stack_size__);

else

   stack_size = ETHR_PAGE_ALIGN(ETHR_KW2B(suggested_stack_size));

(void) pthread_attr_setstacksize(&attr, stack_size);

    }

 

#ifdef ETHR_STACK_GUARD_SIZE

    (void) pthread_attr_setguardsize(&attr, ETHR_STACK_GUARD_SIZE);

#endif

 

    /* Detached or joinable... */

    res = pthread_attr_setdetachstate(&attr,

     (opts && opts->detached

      ? PTHREAD_CREATE_DETACHED

      : PTHREAD_CREATE_JOINABLE));

    if (res != 0)

goto error;

 

    /* Call prepare func if it exist */

    if (ethr_thr_prepare_func__)

twd.prep_func_res = ethr_thr_prepare_func__();

    else

twd.prep_func_res = NULL;

 

    res = pthread_create((pthread_t *) tid, &attr, thr_wrapper, (void*) &twd);

 

    if (res == 0) {

int spin_count = child_wait_spin_count;

 

/* Wait for child to initialize... */

while (1) {

   ethr_sint32_t result;

   ethr_event_reset(&twd.tse->event);

 

   result = ethr_atomic32_read(&twd.result);

   if (result == 0)

break;

 

   if (result > 0) {

res = (int) result;

goto error;

   }

 

   res = ethr_event_swait(&twd.tse->event, spin_count);

   if (res != 0 && res != EINTR)

goto error;

   spin_count = 0;

}

    }

 

    /* Cleanup... */

 

 error:

    dres = pthread_attr_destroy(&attr);

    if (res == 0)

res = dres;

    if (ethr_thr_parent_func__)

ethr_thr_parent_func__(twd.prep_func_res);

    return res;

}

可以看出,线程创建过程是一个标准的pthread线程创建框架。
static void *erl_drv_thread_wrapper(void *vdtid)
{
    int res;
    struct ErlDrvTid_ *dtid = (struct ErlDrvTid_ *) vdtid;
    res = ethr_tsd_set(tid_key, vdtid);
    if (res != 0)
fatal_error(res, "erl_drv_thread_wrapper()");
    return (*dtid->func)(dtid->arg);
}

int

ethr_tsd_set(ethr_tsd_key key, void *value)

{

#if ETHR_XCHK

    if (ethr_not_inited__) {

ETHR_ASSERT(0);

return EACCES;

    }

#endif

    return pthread_setspecific((pthread_key_t) key, value);

}

外覆函数通过pthread_setspecific为线程设置kv私有数据结构,这个数据结构是线程的erlang线程描述符ErlDrvTid,然后以用户给出的参数调用用户的函数。

进入NIF世界后,就可以借助很多erlang虚拟机的功能来探索erlang世界了,此时既可以通过erlang来实现功能,也可以通过c来实现功能,可以将各式各样的c系统移植如erlang虚拟机,扩充和丰富erlang的功能,同时减少开发的难度,性能也将得到很大的提高。

分享到:
评论

相关推荐

    rustler编写erlang nif

    在Erlang生态系统中,Native Implemented Functions (NIFs) 是一种机制,允许开发者用其他语言(如C、C++或Rust)编写性能关键部分的代码,然后在Erlang虚拟机(VM)中调用。Rustler是一个库,专门用于简化使用Rust...

    erlang nif test

    Erlang NIF(Native Implemented Functions)是Erlang虚拟机提供的一种机制,允许开发者用C语言或者其他低级语言编写性能关键部分的代码,并在Erlang系统中无缝调用。这种方式可以充分利用C语言的高效性,同时保持...

    erl_nif_rustler_过程宏写法

    在Erlang中,`NIF (Native Implemented Functions)` 是一种机制,允许开发者使用其他语言(如C或Rust)...通过理解`rustler_macro`的过程宏和Erlang NIF的生命周期,开发者可以轻松地将Rust功能集成到Erlang系统中。

    rustler —用于创建Erlang NIF函数的安全Rust桥-Rust开发

    示例Rustler是一个用于以安全的Rust代码编写Erlang NIF的库。 这意味着应该没有任何办法。 入门指南 示例Rustler是一个用于以安全的Rust代码编写Erlang NIF的库。 这意味着应该没有办法使BEAM(Erlang VM)崩溃。 该...

    erlang port driver test

    Port Driver 可能与其他 Erlang 外部接口技术,如 NIF(Native Implemented Function)或 ETS(Erlang Term Storage)进行了对比。 标签 "erlang post driver test" 强调了测试的焦点是关于 Erlang 的 Port Driver...

    erl_nif 扩展erlang的另外一种方法

    在Erlang中,为了实现与C或其他低级语言的高效交互,Erlang提供了一个名为`erl_nif`的接口。本文将深入探讨`erl_nif`,了解它是如何扩展Erlang的功能,并讨论如何使用它来提升性能。 `erl_nif`(Erlang NIF,Native...

    erlang -c语言程序接口.pdf

    Erlang与C语言接口主要通过两种方式实现:一种是将C语言编写的代码直接嵌入到Erlang程序中;另一种是通过进程间通信(IPC)的方式让Erlang与C语言程序进行交互。Erlang倾向于采用第二种方式,即进程间通信,来与C语言...

    Windows下使用NIF扩展Erlang完整例子

    Windows下使用NIF扩展Erlang完整例子,包含nif工程项目,erlang引用例子。 配套文章:http://blog.csdn.net/mycwq/article/details/17527485

    erlang-rust-nif:在 Rust 中实现的 Erlang NIF 示例

    Rust 中的 Erlang NIF 这是一个如何在 Rust 中实现 NIF 的示例。 它对我有用,也可能对你有用,但如果它吃掉了你的作业,请不要生气。 虽然这将是可行的写现实世界的代码下面这个例子,因为整个erl_nif.h接口可用...

    erlpuzzle:Erlang NIF 到 libpuzzle,一个快速查找视觉相似图像的库

    ErlPuzzle - Erlang 的 libpuzzle NIF Puzzle 库旨在快速找到视觉上相似的图像(gif、png、jpg),即使它们已被调整大小、重新压缩、重新着色或稍微修改。 该库是免费的、轻量级的但非常快速、可配置、易于使用,...

    Erlang应用程序接口(视频,1/4)

    这是第一卷。 在2008 CN Erlounge III的“Erlang应用程序接口”讲演的视频。PPT等其它资料在这里: http://blog.csdn.net/aimingoo/archive/2009/01/14/3777765.aspx 有关信息参见: ...

    erlang-tc:Erlang NIF用于threshold_crypto

    - **Erlang模块**:Erlang代码部分,定义了与NIF交互的接口函数,这些函数在Erlang代码中可以像普通函数一样调用。 - **NIF接口定义**:Erlang模块中会有`erlang:nifEXPORTS`列表,列出所有暴露给Erlang的NIF函数...

    erlsha2:在Erlang NIF中实现的SHA-224,SHA-256,SHA-384,SHA-512

    在Erlang NIF中实现的SHA-224,SHA-256,SHA-384,SHA-512。描述erlsha2库应用程序使用Erlang NIF实施SHA-2安全哈希标准(SHA-224,SHA-256,SHA-384,SHA-512)。 (它也提供纯的Erlang实现,尽管它们比C NIF实现慢...

    esqlite:sqlite的Erlang NIF

    该库以nif库的形式实现,可以最快地访问sqlite数据库。 这可能是有风险的,因为nif库或sqlite数据库中的错误可能会使整个Erlang VM崩溃。 如果您不想冒险,总是可以从单独的erlang节点访问sqlite nif。 特别注意...

    enif_protobuf:使用enif(Erlang nif)的Google Protobuf实现

    **enif_protobuf** 是一个基于 **Erlang ...总之,enif_protobuf是Erlang社区对Google Protobuf的一种强大实现,通过Erlang NIF机制实现了高性能的数据序列化和反序列化,简化了Erlang系统与其他系统之间的数据交换。

    rustler:用于创建Erlang NIF函数的Safe Rust桥

    在Erlang应用中,这些NIF函数可以通过标准的Erlang/Elixir接口调用,就像调用普通的Erlang模块一样。这样,开发者可以在保持Erlang/Elixir应用的并发性和容错性的同时,利用Rust的性能和安全性来处理计算密集型任务...

    用于创建 Erlang NIF 函数的安全 Rust 桥

    盗贼文档|入门|例子Rustler 是一个用安全的 Rust 代码编写 Erlang NIF 的库。这意味着应该没有办法让 BEAM (Erlang VM) 崩溃。该库提供了用于生成与 BEAM 交互的样板的工具,处理 Erlang 术语的编码和解码,并在它们...

    Erlang应用程序接口 - Topic at CN Erlounge III

    我在Erlounge III大会上的讲演PPT。 相关的视频在这里: http://groups.google.com/group/erlang-china/browse_thread/thread/2154c39503795edc

    erlang的mysql驱动接口

    `dizzyd-erlang-mysql-driver` 是一个Erlang库,实现了MySQL的驱动接口。它提供了丰富的API,支持执行SQL查询、事务处理、结果集处理等功能。这个库的版本号为 `a2ae450`,意味着它包含了某些特定的改进和修复。 ##...

Global site tag (gtag.js) - Google Analytics