Linux实时性测试

对于Linux实时性测试,目前我们用了以下方法:

1.写了测试程序,用于测试线程调度时间,主进程和线程的priority都设置为最高,截取如下代码:

 struct sched_param sp;
        memset(&sp,0,sizeof(struct sched_param));
        sp.sched_priority = 99;
        sched_setscheduler(getpid(),SCHED_RR,&sp);

        /* Attr of thread */
        int policy;
        pthread_attr_getschedpolicy(&ThreadAttr , &policy);
        printf("1:SCHED_FIFO = %d, SCHED_OTHER = %d, SCHED_RR = %d,policy = %d\n",SCHED_FIFO,SCHED_OTHER,SCHED_RR,policy);
        pthread_attr_setschedpolicy(&ThreadAttr , SCHED_RR);
        pthread_attr_getschedpolicy(&ThreadAttr , &policy);
        printf("2:SCHED_FIFO = %d, SCHED_OTHER = %d, SCHED_RR = %d,policy = %d\n",SCHED_FIFO,SCHED_OTHER,SCHED_RR,policy);

其中,说明两点,第一,sched_setscheduler()函数将pid所指定进程的调度策略和调度参数分别设置为param指向的sched_param结构中指定的policy和参数。sched_param结构中的sched_priority成员的值可以为任何整数,该整数位于policy所指定调度策略的优先级范围内(含边界值)。policy参数的可能值在头文件中定义。

      如果存在pid所描述的进程,将会为进程ID等于pid的进程设置调度策略和调度参数。

      如果pid为零,将会为调用进程设置调度策略和调度参数。

      如果进程pid含多个进程或轻量进程(即该进程是多进程的),此函数将影响进程中各个子进程。

      更改其他进程的调度参数需要有相应的特权。调用进程必须具有相应的特权,或者是具有PRIV_RTSCHED权限的组的成员,猜能成功调用sched_setscheduler()。如果sched_setscheduler()函数成功地将pid所指定调度策略和调度参数分别设置为policy和结构param指定值 ,则该函数调用成功。

第二,需要了解进程调度,设置为  SCHED_RR,如果设置为SCHED_FIFO,线程就会一直被执行:

      进程调度指的是系统对进程的多种状态之间转换的策略。Linux下的进程调度有3种策略:SCHED_OTHER、SCHED_FIFO和SCHED_RP。

 

      SCHED_OTHER是用于针对普通进程的时间片轮转调度策略。这种策略中,系统给所有的运行状态的进程分配时间片。在当前时间片用完之后,系统从进程中优等级最高的进程中选择进程运行。

      SCHED_FIFO是针对运行的实时性要求比较高、运行时间短的进程调度策略。这种策略中,系统按进入队列的先后进行进程的调度,在没有更高优先级进程到来或者当前进程没有因为等待资源而阻塞的情况下,会一直运行。

      SCHED_RR是针对运行的实时性要求比较高、运行经较长的进程调度策略。这种策略与SCHED_OTHER的策略类似,只不过SCHED_RR进程的优先级要高得多。 系统分配给SCHED_RR的进程时间片,然后轮循运行这些进程,将时间片用完的进程放入队列的末尾。

 

       Linux进程调度月票用的是“有条件可剥夺”的调度方式。普通进程中采用的是SCHED_OTHER的时间片轮循方式,实时进程可以剥夺普通进程。如果普通进程在用户空间运行,则普通进程立即停止运行,将资源让给实时进程vkjsuo通进程运行在内核空间,需要等系统调用返回用户空间后方可剥夺资源。

2.主进程调用 拉高串口的CTS信号,节选如下代码

  while(1)
        {
                ioctl(portHandle, TIOCMGET, &Value);
                Value |= TIOCM_RTS;
                usleep(5000);
                ioctl(portHandle, TIOCMSET, &Value);
        }

线程处理函数中,拉低CTS信号,节选如下代码:

void *MCRThread(void *Param)
{
        int SerialHandle = (int)Param;
        unsigned long int  ModemStatus;
        while(1)
        {
                ioctl(SerialHandle, TIOCMIWAIT, TIOCM_CTS);
                ModemStatus &= ~TIOCM_RTS;
                ioctl(SerialHandle, TIOCMSET, &ModemStatus);
        }
        pthread_exit(NULL);
        return 0;
}

3.ioctl(SerialHandle, TIOCMIWAIT, TIOCM_CTS);其中,TIOCMIWAIT:等待 MSR 改变. 用户在非寻常的情况下请求这个 ioctl, 它想在内核中睡眠直到这个 tty 设备的 MSR 寄存器发生某些事情. arg 参数包含用户在等待的事件类型. 这通常用来等待直到一个状态线变化, 指示有更多的数据发送给设备.参考链接如下:http://oss.org.cn/kernel-book/ldd3/ch18s04.html

4.创建一个线程默认的状态是joinable, 如果一个线程结束运行但没有被join,则它的状态类似于进程中的Zombie Process,即还有一部分资源没有被回收(退出状态码),所以创建线程者应该调用pthread_join来等待线程运行结束,并可得到线程的退出代码,回收其资源(类似于wait,waitpid)

但是调用 pthread_join(pthread_id)后,如果该 线程没有运行结束,调用者会被阻塞,在有些情况下我们并不希望如此,比如在Web服务器中当 主线程为每个新来的链接创建一个子线程进行处理的时候,主线程并不希望因为调用pthread_join而阻塞(因为还要继续处理之后到来的链接),这时可以在子线程中加入代码
pthread_detach( pthread_self())
或者父线程调用
pthread_detach(thread_id)(非阻塞,可立即返回)
这将该子线程的状态设置为detached,则该线程运行结束后会自动释放所有资源

5.测试方法:设备上的串口的RTS(pin7)与CTS(pin8)连接接起来,启动测试程序,使用示波器测试RTS,CTS信号,示波器出现10ms的脉冲信号,脉冲宽度就是interupt Latency。

6.可以写程序和脚本开启多个进程,来测试压力情况下的线程调度时间。


你可能感兴趣的:(测试程序)