进程内无法实现实时 SCHED_FIFO 线程
Can not achieve real time SCHED_FIFO thread within process
大家好!
我正在尝试让第二个线程(串行线程)尽可能接近实时 运行。
在我的第二个生成的串行线程中,我 select() 在串行端口上超时为 3 毫秒。
我也在 select() 之前获得实时...然后在获得 select() 增量时间之后。
问题是有时我没有得到 select 返回 0 的指示(由于 3 毫秒过去,我称之为超时)......但我偶尔会得到比 3 大得多的总时间毫秒(例如 4.447)。
我必须得出结论,串行线程正在被抢占?
有什么想法吗?
我可以使用什么 Linux 命令来查看线程是否被抢占?
谢谢!
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>
#include <signal.h>
#include <termios.h>
#include <fcntl.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/resource.h>
//-----------------------------------
// signal Handler stuff.
//-----------------------------------
static
struct sigaction mySigActTerm;
volatile
int myTerminate = 0;
void terminateHandler(int signum, siginfo_t *info, void *ptr)
{
// set a flag here and get out.
myTerminate = 1;
}
void getNowTime(char* str)
{
time_t rawtime;
time(&rawtime);
ctime_r(&rawtime, str);
// clobber the unwanted newline.
str[24] = '[=11=]';
}
void myResLimit()
{
struct
rlimit procLimit;
char strNowTime[26];
getrlimit(RLIMIT_RTTIME, &procLimit);
getNowTime(strNowTime);
fprintf(stderr, "%s - RLIMIT_RTTIME: soft=%lld, hard=%lld\n", strNowTime, (long long) procLimit.rlim_cur, (long long)procLimit.rlim_max);
getrlimit(RLIMIT_RTPRIO, &procLimit);
getNowTime(strNowTime);
fprintf(stderr, "%s - RLIMIT_RTPRIO: soft=%lld, hard=%lld\n", strNowTime, (long long) procLimit.rlim_cur, (long long) procLimit.rlim_max);
getrlimit(RLIMIT_CPU, &procLimit);
getNowTime(strNowTime);
fprintf(stderr, "%s - RLIMIT_CPU: soft=%lld, hard=%lld\n", strNowTime, (long long) procLimit.rlim_cur, (long long) procLimit.rlim_max);
}
void* serialThread(void* arg)
{
int sfd; // serial file descriptor.
char myChar;
int rtn;
fd_set myfds;
struct
timeval tm_out,
start,
end,
delta;
struct
termios oldtio,
newtio;
sfd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY);
tcgetattr(sfd, &oldtio);
newtio = oldtio;
cfmakeraw(&newtio);
newtio.c_cflag |= CREAD;
newtio.c_cflag |= CLOCAL;
newtio.c_cflag &= ~CSTOPB;
newtio.c_cflag &= ~CRTSCTS;
newtio.c_cflag &= ~CSIZE;
newtio.c_cflag |= CS7;
newtio.c_cflag |= PARENB;
newtio.c_cflag &= ~PARODD;
newtio.c_cc[VTIME] = 1;
newtio.c_cc[VMIN] = 1;
tcflush(sfd, TCIFLUSH);
while (1) {
FD_ZERO(&myfds);
FD_SET(sfd, &myfds);
tm_out.tv_sec = 0;
tm_out.tv_usec = 3000;
// get sys call start time.
gettimeofday(&start, NULL);
rtn = select(sfd+1 ,&myfds, NULL, NULL, &tm_out);
// get sys call end time.
gettimeofday(&end, NULL);
timersub(&end, &start, &delta);
if (rtn == 0) {
fprintf(stderr, "tm_out = %02d.%06d delta = %02d.%06d\n", tm_out.tv_sec, tm_out.tv_usec, delta.tv_sec, delta.tv_usec);
}
else
read(sfd, &myChar, 1);
}
}
//-----------------------------------
// the one and only MAIN.
//-----------------------------------
int main()
{
//-----------------------------------------------
// locals.
int rtn;
char strNowTime[26];
pthread_t serialThdID;
pthread_attr_t serialAttr;
struct
sched_param serialParam;
//-----------------------------------------------
// Log OS resource limits.
myResLimit();
//-----------------------------------------------
// initialize the signals struct.
// ... and setup signals.
memset(&mySigActTerm, 0, sizeof(mySigActTerm));
mySigActTerm.sa_sigaction = terminateHandler;
mySigActTerm.sa_flags = SA_SIGINFO;
sigaction(SIGTERM, &mySigActTerm, NULL);
//-----------------------------------------------
// set initial default pthread attr values.
if ((rtn = pthread_attr_init(&serialAttr)) != 0) {
getNowTime(strNowTime);
fprintf(stderr, "%s - main() - pthread_attr_init()\n%s\n", strNowTime, strerror(rtn));
exit(EXIT_FAILURE);
}
//-----------------------------------------------
// set for best near real time policy.
if ((rtn = pthread_attr_setschedpolicy(&serialAttr, SCHED_FIFO)) !=0) {
getNowTime(strNowTime);
fprintf(stderr, "%s - main() - pthread_attr_setschedpolicy()\n%s\n", strNowTime, strerror(rtn));
exit(EXIT_FAILURE);
}
//-----------------------------------------------
// set to explicit inherit or attr obj will be ignored.
if ((rtn = pthread_attr_setinheritsched(&serialAttr, PTHREAD_EXPLICIT_SCHED)) !=0) {
getNowTime(strNowTime);
fprintf(stderr, "%s - main() - pthread_attr_setinheritsched()\n%s\n", strNowTime, strerror(rtn));
exit(EXIT_FAILURE);
}
//-----------------------------------------------
// set to un-limited thread priority.
serialParam.sched_priority = 0;
if ((rtn = pthread_attr_setschedparam(&serialAttr, &serialParam)) !=0) {
getNowTime(strNowTime);
fprintf(stderr, "%s - main() - pthread_attr_setschedparam()\n%s\n", strNowTime, strerror(rtn));
exit(EXIT_FAILURE);
}
//-----------------------------------------------
// start the new thread.
if ((rtn = pthread_create(&serialThdID, &serialAttr, serialThread, NULL)) == 0) {
getNowTime(strNowTime);
fprintf(stderr, "%s - starting serial thread.\n", strNowTime);
}
else {
getNowTime(strNowTime);
fprintf(stderr, "%s - main() - pthread_create() returned %d\n%s\n", strNowTime, rtn, strerror(rtn));
exit(EXIT_FAILURE);
}
//-----------------------------------------------
// no need to keep this junk if pthread_create() succeeded.
if ((rtn = pthread_attr_destroy(&serialAttr)) != 0) {
getNowTime(strNowTime);
fprintf(stderr, "%s - main() - pthread_attr_destroy()\n%s\n", strNowTime, strerror(rtn));
}
while (myTerminate == 0) {
}
}
好吧,似乎没有人知道为什么这会发生在我身上,但是......
...经过将近一年的挣扎...
...我发现了 post 这正是我正在发生的事情。
我post一个link所以没有其他人会遭受我的命运。
大家好!
我正在尝试让第二个线程(串行线程)尽可能接近实时 运行。
在我的第二个生成的串行线程中,我 select() 在串行端口上超时为 3 毫秒。
我也在 select() 之前获得实时...然后在获得 select() 增量时间之后。
问题是有时我没有得到 select 返回 0 的指示(由于 3 毫秒过去,我称之为超时)......但我偶尔会得到比 3 大得多的总时间毫秒(例如 4.447)。
我必须得出结论,串行线程正在被抢占?
有什么想法吗?
我可以使用什么 Linux 命令来查看线程是否被抢占?
谢谢!
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>
#include <signal.h>
#include <termios.h>
#include <fcntl.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/resource.h>
//-----------------------------------
// signal Handler stuff.
//-----------------------------------
static
struct sigaction mySigActTerm;
volatile
int myTerminate = 0;
void terminateHandler(int signum, siginfo_t *info, void *ptr)
{
// set a flag here and get out.
myTerminate = 1;
}
void getNowTime(char* str)
{
time_t rawtime;
time(&rawtime);
ctime_r(&rawtime, str);
// clobber the unwanted newline.
str[24] = '[=11=]';
}
void myResLimit()
{
struct
rlimit procLimit;
char strNowTime[26];
getrlimit(RLIMIT_RTTIME, &procLimit);
getNowTime(strNowTime);
fprintf(stderr, "%s - RLIMIT_RTTIME: soft=%lld, hard=%lld\n", strNowTime, (long long) procLimit.rlim_cur, (long long)procLimit.rlim_max);
getrlimit(RLIMIT_RTPRIO, &procLimit);
getNowTime(strNowTime);
fprintf(stderr, "%s - RLIMIT_RTPRIO: soft=%lld, hard=%lld\n", strNowTime, (long long) procLimit.rlim_cur, (long long) procLimit.rlim_max);
getrlimit(RLIMIT_CPU, &procLimit);
getNowTime(strNowTime);
fprintf(stderr, "%s - RLIMIT_CPU: soft=%lld, hard=%lld\n", strNowTime, (long long) procLimit.rlim_cur, (long long) procLimit.rlim_max);
}
void* serialThread(void* arg)
{
int sfd; // serial file descriptor.
char myChar;
int rtn;
fd_set myfds;
struct
timeval tm_out,
start,
end,
delta;
struct
termios oldtio,
newtio;
sfd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY);
tcgetattr(sfd, &oldtio);
newtio = oldtio;
cfmakeraw(&newtio);
newtio.c_cflag |= CREAD;
newtio.c_cflag |= CLOCAL;
newtio.c_cflag &= ~CSTOPB;
newtio.c_cflag &= ~CRTSCTS;
newtio.c_cflag &= ~CSIZE;
newtio.c_cflag |= CS7;
newtio.c_cflag |= PARENB;
newtio.c_cflag &= ~PARODD;
newtio.c_cc[VTIME] = 1;
newtio.c_cc[VMIN] = 1;
tcflush(sfd, TCIFLUSH);
while (1) {
FD_ZERO(&myfds);
FD_SET(sfd, &myfds);
tm_out.tv_sec = 0;
tm_out.tv_usec = 3000;
// get sys call start time.
gettimeofday(&start, NULL);
rtn = select(sfd+1 ,&myfds, NULL, NULL, &tm_out);
// get sys call end time.
gettimeofday(&end, NULL);
timersub(&end, &start, &delta);
if (rtn == 0) {
fprintf(stderr, "tm_out = %02d.%06d delta = %02d.%06d\n", tm_out.tv_sec, tm_out.tv_usec, delta.tv_sec, delta.tv_usec);
}
else
read(sfd, &myChar, 1);
}
}
//-----------------------------------
// the one and only MAIN.
//-----------------------------------
int main()
{
//-----------------------------------------------
// locals.
int rtn;
char strNowTime[26];
pthread_t serialThdID;
pthread_attr_t serialAttr;
struct
sched_param serialParam;
//-----------------------------------------------
// Log OS resource limits.
myResLimit();
//-----------------------------------------------
// initialize the signals struct.
// ... and setup signals.
memset(&mySigActTerm, 0, sizeof(mySigActTerm));
mySigActTerm.sa_sigaction = terminateHandler;
mySigActTerm.sa_flags = SA_SIGINFO;
sigaction(SIGTERM, &mySigActTerm, NULL);
//-----------------------------------------------
// set initial default pthread attr values.
if ((rtn = pthread_attr_init(&serialAttr)) != 0) {
getNowTime(strNowTime);
fprintf(stderr, "%s - main() - pthread_attr_init()\n%s\n", strNowTime, strerror(rtn));
exit(EXIT_FAILURE);
}
//-----------------------------------------------
// set for best near real time policy.
if ((rtn = pthread_attr_setschedpolicy(&serialAttr, SCHED_FIFO)) !=0) {
getNowTime(strNowTime);
fprintf(stderr, "%s - main() - pthread_attr_setschedpolicy()\n%s\n", strNowTime, strerror(rtn));
exit(EXIT_FAILURE);
}
//-----------------------------------------------
// set to explicit inherit or attr obj will be ignored.
if ((rtn = pthread_attr_setinheritsched(&serialAttr, PTHREAD_EXPLICIT_SCHED)) !=0) {
getNowTime(strNowTime);
fprintf(stderr, "%s - main() - pthread_attr_setinheritsched()\n%s\n", strNowTime, strerror(rtn));
exit(EXIT_FAILURE);
}
//-----------------------------------------------
// set to un-limited thread priority.
serialParam.sched_priority = 0;
if ((rtn = pthread_attr_setschedparam(&serialAttr, &serialParam)) !=0) {
getNowTime(strNowTime);
fprintf(stderr, "%s - main() - pthread_attr_setschedparam()\n%s\n", strNowTime, strerror(rtn));
exit(EXIT_FAILURE);
}
//-----------------------------------------------
// start the new thread.
if ((rtn = pthread_create(&serialThdID, &serialAttr, serialThread, NULL)) == 0) {
getNowTime(strNowTime);
fprintf(stderr, "%s - starting serial thread.\n", strNowTime);
}
else {
getNowTime(strNowTime);
fprintf(stderr, "%s - main() - pthread_create() returned %d\n%s\n", strNowTime, rtn, strerror(rtn));
exit(EXIT_FAILURE);
}
//-----------------------------------------------
// no need to keep this junk if pthread_create() succeeded.
if ((rtn = pthread_attr_destroy(&serialAttr)) != 0) {
getNowTime(strNowTime);
fprintf(stderr, "%s - main() - pthread_attr_destroy()\n%s\n", strNowTime, strerror(rtn));
}
while (myTerminate == 0) {
}
}
好吧,似乎没有人知道为什么这会发生在我身上,但是...... ...经过将近一年的挣扎... ...我发现了 post 这正是我正在发生的事情。
我post一个link所以没有其他人会遭受我的命运。