精华内容
下载资源
问答
  • 可重入函数
    千次阅读
    2020-08-09 21:38:02

    C++可重入函数和不可重入函数

    可重入函数是指能够被多个线程“同时”调用的函数,并且能保证函数结果正确不必担心数据错误的函数。
    不可重入函数是指不能运行在多任务环境下,除非能保证互斥的函数。

    • 由于使用了未受保护的系统资源,如全局变量区,中断向量表等。
    • 不可重入函数在实时系统设计中被视为不安全函数。

    可重入函数特点:

    • 没有静态数据结构
    • 不返回指向静态数据的指针
    • 所有函数数据由函数的调用者提供
    • 使用auto变量,或通过全局变量的拷贝来保护全局变量
    • 若必须访问全局变量,则利用互斥信号保护
    • 不调用不可重入函数

    不可重入函数特点:

    • 函数中使用了静态变量,无论是全局静态变量还是局部静态变量
    • 函数返回静态变量
    • 函数中调用了不可重入函数
    • 函数体内调用了malloc()或者free()函数
    • 函数体内调用了其他标准I/O函数
    • 函数是singleton中的成员函数,而且使用了不属于线程独立存储的成员变量

    可重入规则改写不可重入函数:

    把一个不可重入函数变成可重入的唯一方法是用可重入规则来重写它

    可重入规则:

    1. 不要使用全局变量。如果必须使用记得用互斥信号量保护,因为别的代码很可能修改这些变量值

    2. 在和硬件发生交互的时候,切记执行类似disinterrupt()之类的操作,就是关闭硬件中断。

      完成交互记得打开中断,在有些系列上,这叫做“进入/退出核心”或者用OS_ENTER_KERNAL/ OS_EXIT_KERNAL来描述。

    3. 不能调用任何不可重入的函数。

    4. 谨慎使用堆栈。最好先在使用前先OS_ENTER_KERNAL

    总之,必须保证中断是安全的

    更多相关内容
  • 主要用于多任务环境中,一个可重入函数简单来说就是可以被中断的函数,也就是说,可以在这个函数执行的任何时刻中断它,转入OS调度下去执行另外一段代码,而返回控制时不会出现什么错误;而不可重入函数由于使用...
  • 主要介绍了Linux 中可重入函数与不可重入函数详解的相关资料,需要的朋友可以参考下
  • 详解可重入函数与不可重入函数

    千次阅读 2022-04-09 18:08:57
    详解函数的重入性;详解可重入函数和不可重入函数;如何设计重入的函数。

    C/C++ 中的可重入函数与不可重入函数

    引言

    在编程语言发展的历程中,“函数”的概念无疑是最历史中最伟大的发明之一。简单来说,函数是完成指定功能的代码集合。

    函数的基本样式:

    int func1 (int a, int b)
    {
        int add1 = a;
        int add2 = b;
        int sum = a + b;
        
        printf("add1 addr=%p, add2 addr=%p, sum addr=%p", &add1, &add2, &sum);
        return sum;
    }
    

    我们开发函数的意义除希望它完成指定的功能外,还在于它可以被很多模块调用,而不必重复开发。如上述执行加法运算的函数,它当然可以被很多模块调用,然后返回传入的两个值 a 和 b 相加的和。

    然而,在我们期望"一个函数"可以满足多个模块的使用需求时,我们还需要考虑当多个模块同时调用同一个函数时的"竞争"问题。这编引出了今天讨论的内容:函数的可重入性和不可重入性。

    “重入”的概念

    重入(re-enter),是指当一个函数 func() 已经被 模块 A 调用时,还可以同时被其他模块B、C调用,并且保证 A、B、C 三个模块都能通过调用函数func() 获取正确的结果。用人话说就是这个函数可以同时被很多模块调用,并且保证每个模块都能得到期望的结果。就问 6 不 6?
    在这里插入图片描述
    可重入函数就是,可以被多个模块(如任务、线程、进程)同时使用,且能保证每个模块结果都正常的函数;由于这种可以被多个模块使用的特性,可重入函数也被称为(多)线程安全函数、(多)进程安全函数、可并发函数。

    "可重入"与“不可重入” 的示例

    示例:

    //可重入函数
    int func1 (char* tag, int a, int b)
    {
        int add1 = a;
        int add2 = b;
        int sum = a + b;
        
        printf("%s func1: : add1 addr=%p, add2 addr=%p, sum addr=%p sum1=%d\r\n",tag, &add1, &add2, &sum, sum);
        return sum;
    }
    // 不可重入函数
    static int global_count;
    int func2 (char *tag, int a, int b)
    {
        int add1 = a;
        int add2 = b;
        // add mux
        int sum = a + b + global_count;
        global_count++;
        
        printf("%s func2: add1 addr=%p, add2 addr=%p, sum addr=%p, global addr=%p, sum2=%d\r\n",tag, &add1, &add2, &sum, &global_count, sum);
        // remove mux
        return sum;
    }
    
    static void task1_process(void *arg)
    {
        char *TASK1_TAG = "TASK1";
        int sub1 = 1, sub2 = 2;
        while (1) {
            func1(TASK1_TAG, sub1, sub2);
            // func2(TASK1_TAG, sub1, sub2);
            vTaskDelay(pdMS_TO_TICKS(1000));
        }
    }
    
    static void task2_process(void *arg)
    {
        char *TASK2_TAG = "TASK2";
        int sub1 = 1, sub2 = 2;
        while (1) {
            func1(TASK2_TAG, sub1, sub2);
            // func2(TASK2_TAG, sub1, sub2);
            vTaskDelay(pdMS_TO_TICKS(1000));
        }
    }
    
    void app_main(void)
    {
        printf("Hello world!\n");
    
        xTaskCreate(&task1_process, "task1", 1024*2, (void *)"1", 2, NULL);
        xTaskCreate(&task2_process, "task2", 1024*2, (void *)"2", 3, NULL);
    }
    

    可重入函数 func1 分析

    当 两个线程(任务)都调用 func1() 时,打印的结果如下所示,task1、task2 得到的结果 sum 都是正确的。特别地,在 task1、task2 中 函数 func1()内的变量 add1、add2、sum 的地址都是不同的。这意味着,在 task1 中的 func1() 使用的是 task1 对应的内存空间,在 task2 中的 func1() 使用的是 task2 对应的内存空间。

    Hello world!
    TASK2 func1: : add1 addr=0x3ffb7cb0, add2 addr=0x3ffb7cb4, sum addr=0x3ffb7cb8 sum1=3
    TASK1 func1: : add1 addr=0x3ffb74b0, add2 addr=0x3ffb74b4, sum addr=0x3ffb74b8 sum1=3
    TASK2 func1: : add1 addr=0x3ffb7cb0, add2 addr=0x3ffb7cb4, sum addr=0x3ffb7cb8 sum1=3
    TASK1 func1: : add1 addr=0x3ffb74b0, add2 addr=0x3ffb74b4, sum addr=0x3ffb74b8 sum1=3
    

    我们可以得到这样的结论: 两个 task(也可称为两个模块、线程)虽然调用的是同一个函数,但函数内的变量使用的是相对独立的地址来存储数据,因此数据之间互不干扰。

    不可重入函数 func2 分析

    当 两个线程(任务)都调用 func2() 时,打印的结果如下所示,task1、task2 得到的结果 sum 出现混乱,task2 的 结果,理应是 4、5、6 这样以1 递增,但在第三次中得到的结果是7 。特别地,在 task1、task2 中 函数 func2()内的变量 add1、add2、sum 的地址都是不同的,但函数内的变量 global_count 的地址是固定的 0x3ffb2a70 。这意味着,在 task1 中的 func2() 使用的变量 global_count 与在 task2 中的 func2() 使用的变量 global_count 是 同一个。

    Hello world!
    TASK2 func2: add1 addr=0x3ffb7cc0, add2 addr=0x3ffb7cc4, sum addr=0x3ffb7cc8, global addr=0x3ffb2a70, sum2=4
    TASK1 func2: add1 addr=0x3ffb74b0, add2 addr=0x3ffb74b4, sum addr=0x3ffb74b8, global addr=0x3ffb2a70, sum2=3
    TASK2 func2: add1 addr=0x3ffb7cc0, add2 addr=0x3ffb7cc4, sum addr=0x3ffb7cc8, global addr=0x3ffb2a70, sum2=5
    TASK1 func2: add1 addr=0x3ffb74b0, add2 addr=0x3ffb74b4, sum addr=0x3ffb74b8, global addr=0x3ffb2a70, sum2=6
    TASK2 func2: add1 addr=0x3ffb7cc0, add2 addr=0x3ffb7cc4, sum addr=0x3ffb7cc8, global addr=0x3ffb2a70, sum2=7
    TASK1 func2: add1 addr=0x3ffb74b0, add2 addr=0x3ffb74b4, sum addr=0x3ffb74b8, global addr=0x3ffb2a70, sum2=8
    

    我们可以得到这样的结论: 两个 task(也可称为两个模块、线程)虽然调用的是同一个函数,但函数内若存在共享的变量(如上述的 global_count),则该函数内的数据之间可能发生干扰,导致出现不可预知的错误。

    可重入与不可重入的底层原因

    为什么上述函数 func1 是可重入的,而 func2 是不可重入的?

    我们通过打印函数内的地址,发现可重入的函数内的变量使用的是对应模块的相对独立的地址来存储数据;

    可重入的原理如下图所示,三个模块都调用了 func,但 func 分别使用对应三个模块的内存空间,它们各玩各,互不干扰,嘿嘿。
    在这里插入图片描述
    不可重入的函数内部使用了共享的一段空间来存储数据,当三个模块同时访问 func 时,将间接地同时共用一个变量 global_count,导致数据之间的干扰。
    在这里插入图片描述

    如何写出可重入的函数

    一句话概况:要么仅使用本地变量,要么在使用共享资源时添加保护,来避免共享资源之间的干扰。

    具体地,在函数中要注意下述行为:

    1)函数内减少使用全局变量,以及静态数据,若必须使用,请添加保护。

    2)函数内减少使用malloc()\free()、以及标准I\O 的函数(其一些子函数不可重入,如 printf()),若必须使用,请添加保护。

    3)函数内对设备硬件资源,,如 UART 的访问,要注意关闭中断,使用后再重新开启中断。

    4)函数内不调用其他不可重入的子函数。

    5)注意评估模块的堆栈空间,谨防堆栈不够大,导致的堆栈溢出。

    6)函数中不要使用浮点运算(这个与处理器相关,但部分处理器的浮点运算都是不可重入的)。

    (预告:使用互斥锁,对共享资源进行保护)
    (码字不易,谢谢点赞及收藏)

    展开全文
  • 可重入函数

    千次阅读 2021-05-04 12:08:43
    1、可重入函数:2、不可重入函数:3、注意事项: 一、全局变量异步IO可能会造成什么问题? 父子进程分别对累加: #include <stdio.h> #include <signal.h> #include <unistd.h> #include <...

    一、全局变量异步IO可能会造成什么问题?

    父子进程分别对累加:

    #include <stdio.h>
    #include <signal.h>
    #include <unistd.h>
    #include <stdlib.h>
    
    // 父子进程分别对n进行累加
    // 每隔1秒,相互发送信号通知累加
    int n = 0, flag = 0;
    
    void sys_err(char *str)
    {
    	perror(str);
    	exit(EXIT_FAILURE);
    }
    
    void deal_sig_child(int signo)
    {
    	printf("I am child %d\t%d\n", getpid(), n);
    	n += 2;
    	flag = 1;	// 计数完成
    	//sleep(1);
    }
    
    void deal_sig_parent(int num)
    {
    	printf("I am parent %d\t%d\n", getpid(), n);
    	n += 2;
    	flag = 1;	// 计数完成
    	//sleep(1);
    }
    
    int main()
    {
    	pid_t pid;
    	struct sigaction act;
    
    	if ((pid = fork()) < 0)
    	{
    		sys_err("fork");
    	}
    	else if (pid > 0)
    	{
    		n = 1;
    		sleep(1); // 保证子进程注册信号的动作能完成
    		act.sa_handler = deal_sig_parent;
    		sigemptyset(&act.sa_mask);
    		act.sa_flags = 0;
    		sigaction(SIGUSR2, &act, NULL);	//	注册SIGUSR2的捕捉函数
    
    		// 父进程先开始累加
    		deal_sig_parent(0);
    		
    		while(1)
    		{
    			// wait for signal
    			if (flag == 1) 
    			{
    				kill(pid, SIGUSR1);
                      // ----------------这里可能失去CPU
    				flag = 0;
    			}
    		}
    	}
    	else if (pid == 0)
    	{
    		n = 2;
    		act.sa_handler = deal_sig_child;
    		sigemptyset(&act.sa_mask);
    		act.sa_flags = 0;
    		sigaction(SIGUSR1, &act, NULL);	//	注册SIGUSR1的捕捉函数
    
    		while(1)
    		{
    			// wait for signal
    			if (flag == 1) 
    			{
    				kill(getppid(), SIGUSR2); // 给父进程发送SIGUSR2
    				flag = 0;
    			}
    		}
    	}
    
    	return 0;
    }
    
    

    SIGUSR1: 10,用户定义的信号。即程序员可以在程序中定义并使用该信号。默认动作为终止进程。

    SIGUSR2: 12,另一个用户定义的信号。即程序员可以在程序中定义并使用该信号。默认动作为终止进程。

      如果注释掉代码中的两处sleep(1),会出现一个问题:n累加一会后,不会再累加,程序进入循环等待。原因如下:

    1. 父进程调用kill给子进程发送信号,通知开始计数。
    2. 父进程在执行flag=0前可能会失去CPU,等待CPU。
    3. 而子进程计数完成,会发送信号给父进程。
    4. 父进程获得CPU后,先调用信号处理函数,将 flag = 1;
    5. 父进程处理完信号后,恢复到断点继续处理程序,执行flag = 0,flag 的值被覆盖。
    6. 此时子进程不再给父进程发送信号,父进程也不能给子进程发送信号,程序陷入死循环。

    解决方法:

    1. 加锁;
    2. 不使用全局变量,使信号处理函数成为可重入函数。

    二、什么是可重入函数?

      一个函数在被调用执行期间(尚未调用结束),由于某种时序又被重复调用,称之为重入。根据函数实现的方法分为可重入函数不可重入函数两种。

    1、可重入函数

    int main()
    {
        func(a) {
            ...
            func(a);
            ...
        }
    }
    
    int main()
    {
        func(a);
        func(a);
    }
    
    // 如果上面两个main函数执行的结果一致,则称func(int a)为可重入函数。
    

      递归调用与连续调用多次,结果一致,就是可重入函数。

    2、不可重入函数

    在这里插入图片描述


      显然,insert函数是不可重入函数,重复调用,会导致意外的结果。究其原因,是该函数内部实现使用了全局变量head

    3、注意事项

    1. 定义可重入函数,函数内不能含有全局变量及static变量,不能使用malloc、free。

    2. 信号捕捉函数应该设计为可重入函数。

    3. 信号处理程序可以调用的可重入函数可以参考man 7 signal

    4. 没有包含在上述列表中的函数大多是不可重入函数。其原因为:

      a) 使用了静态数据结构

      b) 调用了malloc或free

      c) 是标准IO函数

    展开全文
  • 主要给大家介绍了关于Golang教程之不可重入函数的实现方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
  • 本文较详细的介绍了keilc51再入函数和模拟堆栈的一些概念和实现原理,通过一个简单的程序来剖析keilc51在大存储模式下可重入函数的调用过程,希望能为keilc51和在51系列单片机上移植嵌入式实时操作系统的初学者...
  • C语言之可重入函数 和不可重入函数

    千次阅读 2017-09-06 21:51:32
    可重入函数  在 实时系统的设计中,经常会出现多个任务调用同一个函数的情况。如果这个函数不幸被设计成为不重入的函数的话, 那么不同任务调用这个函数时可能修改其他任 务调用这个函数的数据,从而导致不...

     

    可重入函数


          在 实时系统的设计中,经常会出现多个任务调用同一个函数的情况。如果这个函数不幸被设计成为不可重入的函数的话,

    那么不同任务调用这个函数时可能修改其他任 务调用这个函数的数据,从而导致不可预料的后果。

    那么什么是可重入函数呢?所谓可重入是指一个可以被多个任务调用的过程,任务在调用时不必担心数据是否会 出错。

    不可重入函数在实时系统设计中被视为不安全函数。




      满足下列条件的函数多数是不可重入的:


    (1)函数体内使用了静态的数据结构;


    (2)函数体内调用了malloc()或者free()函数;


    (3)函数体内调用了标准I/O函数。




    如何写出可重入的函数?在函数体内不访问那些全局变量,不使用静态局部变量,坚持只使用缺省态(auto)局部变量,

    写出的函数就将是可重入的。如果必须访问全局变量,记住利用互斥信号量来保护全局变量。

    或者调用该函数前关中断,调用后再开中断。


     


    可重入函数可以被一个以上的任务调用,而不必担心数据被破坏。可重入函数任何时候都可以被中断

    ,一段时间以后又可以运行,而相应的数据不会丢失。可重入函数或者只使用局部变量,

    即保存在CPU寄存器中或堆栈中;或者使用全局变量,则要对全局变量予以保护。




    说法2:




    一个可重入的函数简单来说,就是:可以被中断的函数。就是说,你可以在这个函数执行的任何时候中断他的运行,

    在任务调度下去执行另外一段代 码而不会出现什么错误。而不可重入的函数由于使用了一些系统资源,比如全局变量区,

    中断向量表等等,所以他如果被中断的话,可能出现问题,所以这类函数是 不能运行在多任务环境下的。


    基本上下面的函数是不可重入的
    (1)函数体内使用了静态的数据结构;
    (2)函数体内调用了malloc()或者free()函数;
    (3)函数体内调用了标准I/O函数。


    把一个不可重入函数变成可重入的唯一方法是用可重入规则来重写他。
    其实很简单,只要遵守了几条很容易理解的规则,那么写出来的函数就是可重入的。


    第一,不要使用全局变量。因为别的代码很可能覆盖这些变量值。


    第二,在和硬件发生交互的时候,切记执行类似disinterrupt()之类的操作,就是关闭硬件中断。完成交互记得打开中断,在有些系列上,这叫做“进入/退出核心”或者用OS_ENTER_KERNAL/OS_EXIT_KERNAL来描述。//这是临界区保护


    第三,不能调用任何不可重入的函数。


    第四,谨慎使用堆栈。最好先在使用前先OS_ENTER_KERNAL。


    还有一些规则,都是很好理解的,总之,时刻记住一句话:保证中断是安全的!


     


     

    相信很多人都看过下面这个面试题


    中断是嵌入式系统中重要的组成部分,这导致了很多编译开发商提供一种扩展—让标准C支持中断。具代表事实是,产生了一个新的关键字 __interrupt。下面的代码就使用了__interrupt关键字去定义了一个中断服务子程序(ISR),请评论一下这段代码的。

     

    __interrupt double compute_area (double radius) 
    {
        double area = PI * radius * radius;
        printf("\nArea = %f", area);
        return area;
    }
    



    这个函数有太多的错误了,以至让人不知从何说起了:
    1)ISR 不能返回一个值。如果你不懂这个,那么你不会被雇用的。
    2) ISR 不能传递参数。如果你没有看到这一点,你被雇用的机会等同第一项。
    3) 在许多的处理器/编译器中,浮点一般都是不可重入的。有些处理器/编译器需要让额处的寄存器入栈,

    有些处理器/编译器就是不允许在ISR中做浮点运算。此外,ISR应该是短而有效率的,在ISR中做浮点运算是不明智的。
    4) 与第三点一脉相承,printf()经常有重入和性能上的问题。如果你丢掉了第三和第四点,我不会太为难你的。

    不用说,如果你能得到后两点,那么你的被雇用前景越来越光明了。
     
     
    -->
    如果说中断服务程序有返回值,那么它的值返回给谁呢?
    在系统的运行过程中,一定是某种中断源出发了相应的中断,系统上挂接的中断服务程序进行现场的处理,例如告警等操作,然后清中断。
    也就是说中断服务程序链接在某一类中断源上,而这些中断源的产生是随机的,所以,中断服务程序并没有一个固定的调用者,

    也没有固定的返回地址,所以返回值也没有用


    我的问题是,这里所说的printf()经常有重入的问题,具体是指什么?有人能给解释一下么?
    这个概念在嵌入式操作系统中比较重要,由于存在任务的调度,它实时系统,可剥夺型内核中是危险的,如同一个安静的水雷。

    可能会被触发,也可能安然无恙。由于它运行结果的不可预期性,会使系统带来隐患。



    下面引用一段别人的解释:


    这主要在多任务环境中使用,一个可重入的函数简单来说,就是:可以被中断的函数。就是说,你可以在这个函数执行的任何时候中断他的运行,

    在OS的调度下去执行另外一段代码而不会出现什么错误。而不可重入的函数由于使用了一些系统资源,

    比如全局变量区,中断向量表等等,所以他如果被中断的话,可能出现问题,所以这类函数是不能运行在多任务环境下的。


    把一个不可重入函数变成可重入的唯一方法是用可重入规则来重写他。


    其实很简单,只要遵守了几条很容易理解的规则,那么写出来的函数就是可重入的。


    第一,不要使用全局变量。因为别的代码很可能覆盖这些变量值。


    第二,在和硬件发生交互的时候,切记执行类似disinterrupt()之类的操作,就是关闭硬件中断。完成交互记得打开中断,在有些系列上,

    这叫做“进入/退出核心”或者用OS_ENTER_KERNAL/OS_EXIT_KERNAL来描述。


    第三,不能调用任何不可重入的函数。


    第四,谨慎使用堆栈。最好先在使用前先OS_ENTER_KERNAL。


    还有一些规则,都是很好理解的,总之,时刻记住一句话:保证中断是安全的!


    通俗的来讲吧:由于中断是可能随时发生的,断点位置也是无法预期的。所以必须保证每个函数都具有不被中断发生,

    压栈,转向ISR,弹栈后继续执行影响的稳定性。也就是说具有不会被中断影响的能力。既然有这个要求,

    你提供和编写的每个函数就不能拿公共的资源或者是变量来使用,因为该函数使用的同时,ISR(中断服务程序)

    也可那会去修改或者是获取这个资源,从而有可能使中断返回之后,这部分公用的资源已经面目全非。




    满足下列条件的函数多数是不可重入的:


    (1)函数体内使用了静态的数据结构;


    (2)函数体内调用了malloc()或者free()函数;


    (3)函数体内调用了标准I/O函数。




         下面举例加以说明。


    可重入函数

     

    void strcpy(char* lpszDest, char* lpszSrc)
    
    
    {
    
    
         while(*lpszDest++ = *lpszSrc++);
    
    
         *dest=0;
    
    
    }




    非可重入函数1

     

    char cTemp;            // 全局变量
    
    
    void SwapChar1(char* lpcX, char* lpcY)
    
    
    {
    
    
         cTemp = *lpcX; 
    
    
         *lpcX = *lpcY; 
    
    
         lpcY = cTemp;     // 访问了全局变量,在分享内存的多个线程中可能造成问题
    
    
    }




    非可重入函数2

     

    void SwapChar2(char* lpcX, char* lpcY)
    
    
    {
    
    
         static char cTemp;  // 静态局部变量
    
    
         cTemp = *lpcX; 
    
    
         *lpcX = *lpcY; 
    
    
         lpcY = cTemp;   // 使用了静态局部变量,在分享内存的多个线程中可能造成问题
    
    
    }




         如何写出可重入的函数?在函数体内不访问那些全局变量,不使用静态局部变量,坚持只使用局部变量,写出的函数就将是可重入的。

    如果必须访问全局变量,记住利用互斥信号量来保护全局变量。

     

     

    备注:


    可重入和线程安全(Thread-Safe)是两个不同的概念:可重入函数一定是线程安全的;线程安全的函数可能是重入的,也可能是不重入的;线程不安全的函数一定是不可重入的。

    reentrant函数与是不是多线程无关,如果是reentrant函数,那么要求即使是同一个进程(或线程)同时多次进入该函数时,该函数仍能够正确的运作.
    该要求还蕴含着,如果是在多线程环境中,不同的两个线程同时进入该函数时,该函数也能够正确的运作.

    thread safe函数是与多线程有关的,它只是要求不同的两个线程同时对该函数的调用在逻辑上是正确的.

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

    本文转自:

    http://www.cnblogs.com/AlwaysOnLines/p/3912680.html

    https://blog.csdn.net/zyboy2000/article/details/51120771

     

     

    展开全文
  • 可重入函数

    千次阅读 2019-02-25 11:59:27
    可重入函数 文章目录不可重入函数举例保证函数的重入性的方法:实时系统 举例 malloc维护内部的链表, 而且这个过程不是原子的。譬如, 应用正在执行一个函数, 该函数刚好调用malloc. 此时应用catch到某个signal...
  • c语言可重入函数

    2019-08-30 15:29:11
    可重入函数主要用于多任务环境中,一个重入的函数简单来说就是可以被中断的函数,也就是说,可以在这个函数执行的任何时刻中断它,转入OS调度下去执行另外一段代码,而返回控制时不会出现什么错误;而不重入的...
  • 可重入函数    在 实时系统的设计中,经常会出现多个任务调用同一个函数的情况。如果这个函数不幸被设计成为不重入的函数的话,那么不同任务调用这个函数时可能修改其他任 务调用这个函数的数据,从而导致不...
  • 可重入函数与不可重入函数的举例,详细阐述了如何避免不可重入函数
  • 浅谈可重入函数与不可重入函数

    万次阅读 多人点赞 2018-08-16 20:55:25
    这样的函数是不安全的函数,也叫不可重入函数。 相反,肯定有一个安全的函数,这个安全的函数又叫可重入函数。那么什么是可重入函数呢?所谓重入是指一个可以被多个任务调用的过程,任务在调用时不必担心数据是否...
  • 关注+星标公众号,不错过精彩内容转自 | C语言与CPP编程1 前言 最近在公司维护的项目中碰到一个解决了定位很久的 bug , bug 找到的时候发现犯了很低级的错误——在中断处理函数...
  • linux中可重入函数、不可重入函数

    千次阅读 2018-12-10 16:39:14
    1、结论:可重入函数必然是线程安全函数和异步信号安全函数; 线程安全函数不一定是可重入函数。 例如:strtok是既不重入的,也不是线程安全的;加锁的strtok不是重入的,但线程安全。 2、不重入导致死锁的...
  • 可重入函数和不可重入函数

    千次阅读 2018-11-10 16:24:04
    一、可重入函数 为了增强程序的稳定性,在信号处理函数中应使用可重入函数。 所谓可重入函数是指一个可以被多个任何调用的过程,任务在调用时不必担心数据是否出错。因为进程在收到信号后,就将跳转到信号处理函数...
  • C语言 可重入函数

    千次阅读 2019-05-12 15:47:06
    什么是可重入函数 可重入函数指一个同时被多个任务调用的过程,当一个函数满足下列条件时多为不可重入函数 (1)函数中使用了静态的数据结构; (2)函数中使用了malloc()、free()函数; (3)函数汇总调用了...
  • 线程安全:简单来说线程安全就是多个线程并发同一...(2)函数状态随着被调用,状态发生变化的函数; (3)返回指向静态变量指针的函数; (4)调用线程不安全函数函数; 常见的线程安全的情况: (1)每个线程对全局...
  • 要解释可重入函数为何物,首先需要区分单线程程序和多线程程序。典型UNIX程序都具有一条执行线程,贯穿程序始终,CPU围绕单条执行逻辑来处理指令。而对于多线程程序而言,同一进程却存在多条独立、并发的执行逻辑流...
  • 可重入函数c语言

    2014-07-29 09:08:16
    c语言重入函数的含义,用法和案例讲解,也许有用
  • 如何实现可重入函数

    千次阅读 2018-07-23 22:18:37
    重入(reentrant)函数可以由多于一个...可重入函数可以在任意时刻被中断,稍后再继续运行,不会丢失数据。可重入函数要么使用本地变量,要么在使用全局变量时保护自己的数据。 来看两段代码 //重入 void ex...
  • /不可重入函数

    千次阅读 2019-04-16 06:00:43
    根据函数实现的方法分为“可重入函数”和“不可重入函数”两种。看如下程序。 可以看出在进程主控程序的insert函数未执行完时(在执行完p->next=head时,收到一个信号,需要立即去处理信号),马上内核接着...
  • 本文较详细的介绍了keilc51再入函数和模拟堆栈的一些概念和实现原理,通过一个简单的程序来剖析keilc51在大存储模式下可重入函数的调用过程,希望能为keilc51和在51系列单片机上移植嵌入式实时操作系统的初学者...
  • 可重入函数分类 (1)显式可重入函数 如果所有函数的参数都是传值传递的(没有指针),并且所有的数据引用都是本地的自动栈变量(也就是说没有引用静态或全局变量),那么函数就是显示重入的,也就是说不管如何调用...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 269,689
精华内容 107,875
关键字:

可重入函数