【问题标题】:Creating a real time linux threads from bash and linux scheduling从 bash 和 linux 调度创建实时 linux 线程
【发布时间】:2016-02-17 03:08:49
【问题描述】:

我是 linux 内核开发的新手。我试图学习线程创建和同步。我的最终目标是创建两个线程,这两个线程使用由信号量保护的共享资源。

代码是

#include<stdio.h>
#include<string.h>
#include<pthread.h>
#include<stdlib.h>
#include<unistd.h>
#include<semaphore.h>

sem_t sema_obj;

pthread_t tid[2];

int shared_val = 0;

void* doSomeThing(void *arg)
{
    unsigned long i = 0;
    pthread_t id = pthread_self();

    for(i=0;i<5;i++){
    printf("\n going to wait %x\n",(unsigned int)id);
    sem_wait(&sema_obj);
    shared_val++;
    sleep(1);
    printf("\n %d The value of shared_val is %d in thread %x \n",(int)i, shared_val, (unsigned int)id);
    sem_post(&sema_obj);
    printf("\n gave up sem %x\n",(unsigned int)id);
    }

    for(i=0; i<(0xFFFFFFFF);i++);

    return NULL;
}

int main(void)
{
    int i = 0;
    int err;
    sem_init(&sema_obj, 0, 1);
    while(i < 2)
    {
    pthread_attr_t attr;
    struct sched_param param;

    pthread_attr_init(&attr);
    pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
    param.sched_priority = 50;
    pthread_attr_setschedparam(&attr, &param);
    //sched_setscheduler(current, SCHED_FIFO, &param);
        err = pthread_create(&(tid[i]), &attr, &doSomeThing, NULL);
    //err = pthread_create(&(tid[i]), NULL, &doSomeThing, NULL);
        if (err != 0)
            printf("\ncan't create thread :[%s]", strerror(err));
        else
            printf("\n Thread created successfully 0x%X \n",(unsigned int)tid[i]);

        i++;
    }
    enter code here
    sleep(60);
    return 0;
}

我正在编译它

gcc -o threads_op -pthread -lrt threads.c

运行代码后,我看到:

 Thread created successfully 0xB75CBB40 

 going to wait b75cbb40

 Thread created successfully 0xB6DCAB40 

 going to wait b6dcab40

 0 The value of shared_val is 1 in thread b75cbb40 

 gave up sem b75cbb40

 going to wait b75cbb40

 1 The value of shared_val is 2 in thread b75cbb40 

 gave up sem b75cbb40

 going to wait b75cbb40

 2 The value of shared_val is 3 in thread b75cbb40 

 gave up sem b75cbb40

 going to wait b75cbb40

 3 The value of shared_val is 4 in thread b75cbb40 

 gave up sem b75cbb40

 going to wait b75cbb40

 4 The value of shared_val is 5 in thread b75cbb40 

 gave up sem b75cbb40

 0 The value of shared_val is 6 in thread b6dcab40 

 gave up sem b6dcab40

 going to wait b6dcab40

 1 The value of shared_val is 7 in thread b6dcab40 

 gave up sem b6dcab40

 going to wait b6dcab40

 2 The value of shared_val is 8 in thread b6dcab40 

 gave up sem b6dcab40

 going to wait b6dcab40

 3 The value of shared_val is 9 in thread b6dcab40 

 gave up sem b6dcab40

 going to wait b6dcab40

 4 The value of shared_val is 10 in thread b6dcab40 

 gave up sem b6dcab40

此进程的 RTPRIO 为“-”, S 1000 4551 4338 - 00:00:00 线程操作

有以下问题,

1) 为什么线程不是实时的,并占据我设置的优先级?

2) 为什么信号量没有被两个线程交替锁定并更新共享变量?两个线程具有相同的优先级。

如果您知道了解linux内核主题的分步教程,请分享。

【问题讨论】:

  • 为什么会提到 Bash?
  • 你不应该对实时应用程序使用睡眠,因为它只是一个最小的时间保证,即你的线程将等待至少 1s ,然后你将拥有你的系统时间粒度。
  • 睡眠唤醒对于实时线程来说会更准确,实际上。但是 sleep() 只有第二个粒度。

标签: linux scheduled-tasks scheduler


【解决方案1】:

一些事情。

首先,我讨厌做事,但你不是在做 linux kernel 开发。您正在编写一个在 linux 上运行的多线程 应用程序。因此,linux-kernel 标签是不合适的。内核开发是关于编写内置于内核中的代码,例如调度程序、设备驱动程序、文件系统驱动程序等。

你已经在inside你的临界区睡了(例如在sem_waitsem_post 之间)。您正在经历“线程饥饿”。在这里查看我的答案:Thread Synchronization C++

由于您使用的是 pthreads,因此使用pthread_mutex_lock/pthread_mutex_unlock 可能会更好。

您也在使用printfs。它们会破坏时间,即使是在调试时也是如此。

您正在尝试执行 SCHED_FIFO 但未检查返回码。只有 root 可以设置一些 RT 调度程序和/或高[er] 优先级。同样,对于调度优先级。

哇! SCHED_FIFO 的优先级 50?如果你真的明白了,任何高于 11 的东西都会以比某些内部内核线程更高的优先级调度你。您可能会锁定系统。 [*]

在您所处的阶段,在您“全力以赴”[使用 RT 调度程序等]之前,以标准优先级使用普通调度程序。你会惊讶于它的表现如何。在调高电压之前先调试你的线程同步代码/逻辑。

实际上,对于具有确定性和低延迟的流畅的高响应 RT 应用程序,我认为您需要更多地规划如何同步、线程之间的队列、类型锁定(例如 RCU、trylocks、锁定尝试超时等) 您需要多少线程?每个人会做什么?你有每个伪代码吗?什么类型的线程环境(例如消费者/生产者,主/从/工人)。你的线程会做“偷工作”吗?等等等等。你会使用IPC消息传递、共享内存吗?多少数据?线程之间的数据带宽是多少?

[*] 我知道这一点的原因是,我是一个实时系统的开发人员,该系统有 50 个线程、8 个内核,并且与多个设备驱动程序和 FPGA 以及大量 DMA 不断交互 [这么多,我们有用 PCIe 总线分析仪测量它,以确保总线有足够的带宽]。它现在是一种运输产品。

【讨论】:

    【解决方案2】:

    真正回答问题:

    1) 你怎么知道线程不是实时的?实时进程不同于实时线程。如果你使用 sudo 或 root 运行这个程序,它应该获得实时优先级。

    2) 不保证信号量是公平的。如果您希望其他线程有机会增加值,则必须使用信号量将 sleep() 调用移至临界区之外。发布(释放)信号量不一定会导致重新调度,因此释放线程完全有可能立即循环并再次等待(获取)信号量。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-03-19
      • 2012-03-17
      • 1970-01-01
      • 2012-03-11
      • 2012-01-17
      • 1970-01-01
      • 2012-05-19
      相关资源
      最近更新 更多