linux调度策略

本文探讨了在Windows子系统Ubuntu中SCHED_FIFO调度设置未生效的问题,并通过示例展示了如何创建线程并使用信号量确保优先级调度。作者分享了如何设置线程属性、优先级和同步策略,以实现预期的线程执行顺序。
摘要由CSDN通过智能技术生成

目录

1、代码


1、代码

注:以下代码在windows子系统的ubuntu运行结果不及预期,SCHED_FIFO设置返回成功,但是实际并没有生效,不知为何,请知道原因的小伙伴不吝赐教,感谢!所以代码是运行在云服务器的unbuntu系统,结果符合预期。

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <error.h>
#define _GNU_SOURCE
#include <pthread.h>
#include <errno.h>
#include <sched.h>
#include <sys/syscall.h>
#include <sys/resource.h>
#include <sys/time.h>
#include <semaphore.h>

#define SIZE 1023
#define KEY ((key_t)0x5005)
#define THREAD1 0
#define THREAD2 1

sem_t g_sem;
sem_t g_thread_ind[2];
int create_thread(pthread_t* thread_id, int detach_state, int schedpolicy, int priority, int inherit_sched,
                int scope, char* thread_name, void* (*func)(void*), void* arg);

void* thread1_main_func(void* arg);

void* thread2_main_func(void* arg);

int main()
{
    sem_init(&g_sem, 0, 0);
    sem_init(&g_thread_ind[THREAD1], 0, 1);
    sem_init(&g_thread_ind[THREAD2], 0, 1);
    int ret = 0;
    struct rlimit rlim;
    ret = getrlimit(RLIMIT_RTPRIO, &rlim);
    if(ret != 0)
    {
        printf("error %d for getrlimit\n", errno);
    }
     else
    {
        printf("rlim cur %ld, rlimit max %ld\n", rlim.rlim_cur, rlim.rlim_max);
    }

    ret = getrlimit(RLIMIT_RTTIME, &rlim);
    if(ret != 0)
    {
        printf("error %d for getrlimit\n", errno);
    }
    else
    {
        printf("rlim cur %ld, rlimit max %ld\n", rlim.rlim_cur, rlim.rlim_max);
    }

    pthread_t thread1;
    pthread_t thread2;
    int shmId;
    struct sched_param sp = {0};
    sp.sched_priority = 0;
    ret = sched_setscheduler(getpid(), SCHED_OTHER, &sp);
    if (0 != ret) printf("set sched policy failed!, errno %d\n", errno);
    else printf("get sched policy : %d, SCHED_FIFO = %d, SCHED_OTHER = %d, max pri: %d\n",
    sched_getscheduler(getpid()), SCHED_FIFO, SCHED_OTHER, sched_get_priority_max(SCHED_FIFO));

    shmId = shmget(KEY, SIZE, IPC_CREAT | 0666);
    if (shmId < 0)
    {
        perror("get shm ipc id error");
        return -1;
    }
    printf("shmid %d\n", shmId);
    ret = create_thread(&thread1, PTHREAD_CREATE_DETACHED, SCHED_OTHER, 0, PTHREAD_EXPLICIT_SCHED,
            PTHREAD_SCOPE_SYSTEM, "THREAD1", thread1_main_func, (void*)((long)shmId));
    if (ret != 0)
    {
        printf("create thread failed, errno %d\n", errno);
        return -1;
    }

    ret = create_thread(&thread2, PTHREAD_CREATE_DETACHED, SCHED_FIFO, 99, PTHREAD_EXPLICIT_SCHED,
                    PTHREAD_SCOPE_SYSTEM, "THREAD2", thread2_main_func, (void*)((long)shmId));
    if (ret != 0)
    {
        printf("create thread failed, errno %d\n", errno);
        return -1;
    }
    int loop = 200;
    printf("policy %d \n", sched_getscheduler(0));
    while(1)
    {
        printf("main func start\n");
        for (int loop = 0; loop < 1000000000; loop++);
        sem_post(&g_thread_ind[THREAD1]);
        sem_post(&g_thread_ind[THREAD2]);
        printf("main func end\n");
    }

    return 0;
}

int create_thread(pthread_t* thread_id, int detach_state, int schedpolicy, int priority, int inherit_sched,
                int scope, char* thread_name, void* (*func)(void*), void* arg)
{
    int rc = 0;
    pthread_attr_t thread_attr;

    rc = pthread_attr_init(&thread_attr);
    if (0 == rc && detach_state != PTHREAD_CREATE_JOINABLE)
    {
        rc = pthread_attr_setdetachstate(&thread_attr, detach_state);
    }
    if (0 == rc && schedpolicy != SCHED_OTHER)
    {
        rc = pthread_attr_setschedpolicy(&thread_attr, schedpolicy);
    }

    if (0 == rc && priority != 0)
    {
        struct sched_param schedparam = {0};
        schedparam.sched_priority = priority;
        rc = pthread_attr_setschedparam(&thread_attr, &schedparam);
    }

    if (0 == rc && inherit_sched != PTHREAD_INHERIT_SCHED)
    {
        rc = pthread_attr_setinheritsched(&thread_attr, inherit_sched);
    }

    if (0 ==rc && scope != PTHREAD_SCOPE_SYSTEM)
    {
        rc = pthread_attr_setscope(&thread_attr, scope);
    }

    if (0 != rc) return rc;
    else rc = pthread_create(thread_id, &thread_attr, func, arg);

    if (0 != rc) return rc;
    else return (pthread_setname_np(*thread_id, (const char*)thread_name));
}

void* thread1_main_func(void* arg)
{
    struct sched_param sp = {0};
    sp.sched_priority = 98;
    sched_setscheduler(syscall(SYS_gettid), SCHED_FIFO, &sp);
    int exist_shmid = shmget(KEY, 0, 0666 | IPC_CREAT);

    char* shmaddr = NULL;
    int shmid = (int)((long)arg);
    printf("thread1: shmid %d, exist_shmid %d\n", shmid, exist_shmid);
    shmaddr = (char*)shmat(shmid, NULL, 0);
    if (shmaddr == (char*)-1)
    {
        perror("shmat addr error");
        //pthread_exit(0);
    }
    strcpy(shmaddr, "hi, i am thread1\n");
    printf("thread1 write: %s", shmaddr);

    printf("thread1 policy %d \n", sched_getscheduler(syscall(SYS_gettid)));
    sem_post(&g_sem);
    shmdt(shmaddr);
    while(1)
    {
        sem_wait(&g_thread_ind[THREAD1]);
        printf("thread1 loop start\n");
        for (int loop = 0; loop < 1000000000; loop++);

        printf("thread1 loop end\n");
    }
    pthread_exit(0);
}

void* thread2_main_func(void* arg)
{
    char* shmaddr = NULL;
    int shmid = (int)((long)arg);
    printf("thread2 \n");
    sem_wait(&g_sem);

    printf("thread2 : shmid %d\n", shmid);
    shmaddr = (char*)shmat(shmid, NULL, 0);
    if (shmaddr == (char*)-1)
    {
        perror("shmat addr error");
        //pthread_exit(0);
    }
    printf("thread2 read: %s", shmaddr);

    printf("thread2 policy %d \n", sched_getscheduler(syscall(SYS_gettid)));

    shmdt(shmaddr);
    shmctl(shmid, IPC_RMID, 0);
    sem_destroy(&g_sem);
    while(1)
    {
        sem_wait(&g_thread_ind[THREAD2]);
        printf("thread2 loop start\n");
        for (int loop = 0; loop < 1000000000; loop++);
        printf("thread2 loop end\n");
    }
    pthread_exit(0);
}

运行结果:

主进程设置默认的SCHED_OTHER普通调度策略,并没有设置NICE值。

线程1的调度策略为SCHED_FIFO,优先级98,线程2的调度策略为SCHED_FIFO,优先级99。

如果不使用信号量g_thread_ind,那么线程2将一直循环执行,不过主进程的调度策略为普通调度策略,所以linux会分一点cpu时间给主进程来运行,但是线程1将不会得到调度。因为跑的服务器只有一个cpu,所以也无法为线程1绑定其他的cpu来运行。

于是乎,使用信号量g_thread_ind可以解决这个问题,让线程2阻塞等待信号量,这样线程1就可以执行了。

还有一个需要说明下,线程1和线程2的执行顺序是固定的,说明信号量有优先级唤醒问题,线程2的优先级更高,所以先运行。

 top -H -p pid命令查看线程调度策略实现结果:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值