c - Pthread 优先级和调度

标签 c pthreads scheduling thread-priority

我正在尝试使用 Pthreads 来设置优先级和调度策略。

我修改了一个简单的套接字(可在线下载),带有一个服务器和几个客户端。这些客户端只是向服务器发送一个字符串。

服务器正在为每个连接的客户端创建一个新线程,并为每个新连接设置更高的优先级,这意味着最后一个连接的客户端是具有最高优先级的。我期望的结果是具有最高优先级的线程是打印出来的线程,直到该客户端连接,而其他线程应该等待。

但是,这不是我得到的结果。无论如何,线程都会被执行,即使是优先级较低的线程。我什至尝试了几种配置,例如使用 pthread_join,但在这种情况下,调度程序将等待该线程完成执行,如果调用另一个具有更高优先级的线程(在我的示例中另一个客户端连接),这是错误的,因为它应该将 CPU 释放给这个新创建的线程。

代码如下:

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <pthread.h>
#include <sched.h>
#include <sys/time.h>

#define PORTNUMBER 8888

int prioInit = 30; //global variable to initialize priority

struct serverParm 
{
       int connectionDesc;
};

//function used to increase priority to new threads
void addPrio(int *prio)
{
  *prio = *prio + 10;
}

void *serverThread(void *parmPtr) 
{
  #define PARMPTR ((struct serverParm *) parmPtr)
  int recievedMsgLen;
  char messageBuf[1025];

  struct sched_param Priority_Param; //struct to set priority
  int policy=SCHED_FIFO; //kind of policy desired, either SCHED_FIFO or SCHED_RR, otherwise Linux uses SCHED_OTHER

  // Server thread code to deal with message processing
  printf("DEBUG: connection made, connectionDesc=%d\n",
        PARMPTR->connectionDesc);

  pthread_t self_id= pthread_self(); // I ask for the tid..
  Priority_Param.sched_priority = prioInit; //.. set the priority (the higher the sooner it is executed, min at 1, max at 99)..
  addPrio(&prioInit); //..increase the base priority..
  if(pthread_setschedparam(self_id, policy, &Priority_Param) != 0) //.. and set the scheduling options.
  {
    printf("Error Set Sched\n");
    perror("");
    exit(1);
  }

  if (PARMPTR->connectionDesc < 0) 
  {
    printf("Accept failed\n");
    exit(1);   
  }

  // Receive messages from sender
  while ((recievedMsgLen=
        read(PARMPTR->connectionDesc,messageBuf,sizeof(messageBuf)-1)) > 0) 
  {
    recievedMsgLen[messageBuf] = '\0';
    printf("Message: %s\n",messageBuf);
  }
  close(PARMPTR->connectionDesc);  // Avoid descriptor leaks 
  free(PARMPTR);                   // And memory leaks                        
}

int main () 
{
  int listenDesc;
  struct sockaddr_in myAddr;
  struct serverParm *parmPtr;
  int connectionDesc;
  pthread_t threadID;

  // Create socket from which to read 
  if ((listenDesc = socket(AF_INET, SOCK_STREAM, 0)) < 0) 
  {
    perror("open error on socket");
    exit(1);
  }

  // Create "name" of socket
  myAddr.sin_family = AF_INET;
  myAddr.sin_addr.s_addr = INADDR_ANY;
  myAddr.sin_port = htons(PORTNUMBER);

  if (bind(listenDesc, (struct sockaddr *) &myAddr, sizeof(myAddr)) < 0) 
  {
    perror("bind error");
    exit(1);
  }

  // Start accepting connections
  listen(listenDesc,5);

  while (1)
  {
    // Wait for a client connection
    connectionDesc = accept(listenDesc, NULL, NULL);

    // Create a thread to actually handle this client
    parmPtr = (struct serverParm *)malloc(sizeof(struct serverParm));
    parmPtr->connectionDesc = connectionDesc;
    if (pthread_create(&threadID, NULL, serverThread, (void *)parmPtr) 
          != 0) 
    {
      perror("Thread create error");
      close(connectionDesc);
      close(listenDesc);
      exit(1);
    }

    printf("Parent ready for another connection\n");
  }

}

我正在使用 -pthread 选项进行编译并以 root 身份运行,以便设置和更改策略和优先级。我肯定在这里遗漏了一些东西,但我也想知道是否可以真正使用和更改调度选项,以便具有类似于实时的行为。

最佳答案

当必须在两个或多个可运行线程之间做出选择时,调度程序策略和优先级用于确定哪个线程将运行

如果您的高优先级线程阻塞在 read() 中,那么它就没有资格运行,而可运行的低优先级线程将有机会运行。优先级的意思是,即使所有可用的 CPU 核心都在运行低优先级线程,当数据从网络到达高优先级线程时,低优先级线程将立即被抢占,以便高优先级线程可以跑。

如果您想查看优先级的影响,让一个低优先级线程做大量工作,这样它几乎总是在使用 CPU:您的高优先级线程仍应立即响应网络输入。

(但是如果你这样做,要么对低优先级线程使用非实时优先级,要么确保你打开了一个以高实时优先级运行的 shell,这样低优先级线程就不会'在需要时阻止您的 shell 运行)。

旁注:您的 addPrio() 函数很活泼——它应该在对 *prio 的更改周围锁定一个互斥量。

关于c - Pthread 优先级和调度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32839010/

相关文章:

c - 将可变参数传递给 printf

c - 将数据传输到工作线程的回调或从工作线程的回调传输数据

c - Posix Pthread 互斥

c - 如何在 Windows 上设置 pthreads?

c++ - 内核模块和 SCHED_RR 线程的优先级

python - 如何限制函数可以运行的时间(添加超时)?

php - 如何通过Linux服务器调用任何php类的方法

c - 32 位 CRC 计算与在线生成器不匹配

c++ - 如何转储 DSA_SIG 或 RSA_SIG

c - 如何开始使用 ARM 处理器?