首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从bash和linux调度创建实时linux线程

从bash和linux调度创建实时linux线程
EN

Stack Overflow用户
提问于 2015-11-16 11:54:53
回答 2查看 2.1K关注 0票数 1

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

代码是

代码语言:javascript
复制
#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;
}

我用以下命令编译它:

代码语言:javascript
复制
gcc -o threads_op -pthread -lrt threads.c

在我运行代码之后,我看到:

代码语言:javascript
复制
 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

对于此过程,实时优先级是'-‘,S 1000 4551 4338 - 00:00:00 threads_op

有以下问题,

1)为什么线程不是实时的,而是采用我设置的优先级?

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

如果你知道一步一步的实践教程来理解linux内核的主题,请分享。

EN

回答 2

Stack Overflow用户

发布于 2015-11-16 16:58:48

几件事。

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

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

既然您使用的是pthread,那么使用pthread_mutex_lock/pthread_mutex_unlock可能会更好。

您还在使用printfs。它们会打乱计时,即使是调试。

您正在尝试执行SCHED_FIFO,但没有检查返回代码。只有root可以设置一些RT调度程序和/或更高的优先级。同样,对于调度优先级也是如此。

哇!SCHED_FIFO的优先级是50?如果你真的得到了它,任何高于11的线程都会以比一些内部内核线程更高的优先级来调度你。您可能会将系统锁定为固态。*

在您所处的阶段,在您使用RT调度器等“全力以赴”之前,请以标准优先级使用普通调度器。你会惊讶于它的性能有多好。在启动电压之前,首先调试线程同步代码/逻辑。

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

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

票数 4
EN

Stack Overflow用户

发布于 2018-11-03 14:21:55

要实际回答这些问题:

1)你怎么知道线程不是实时的?实时进程不同于实时线程。如果您以sudo或root身份运行此程序,它将获得实时优先级。

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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33728259

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档