我正在尝试使用 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/