- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我遇到一种情况,需要在阻止操作之前启动到期计时器。如果在预定的时间间隔内控制仍未脱离阻止操作,那么我需要继续进行并继续其他 Activity 。该程序不应在计时器到期时终止。而是我必须执行阻塞操作之后的代码。在以下代码段中,计时器到期后,我需要转到B点而不退出。工作环境是ubuntu 18.04,代码在c中。我已经探索了setitimer
函数调用以及与信号处理程序相关的函数。但是控制不会跳过阻塞操作并继续执行后续代码。
Program to create a semaphore and setting the semaphore for use by another program.
int main(int argc,char *argv[])
{
key_t SemKey = 0x12345 ;
int SemId = -1;
int NumOfSems = 2 ;
int Flag ;
int RetStat ;
char choice = 'n' ;
struct
{
int val;
struct semid_ds *buf;
ushort array[2] ;
} Arg ;
Flag = IPC_CREAT | IPC_EXCL | 0666 ;
SemId = semget(SemKey,NumOfSems,Flag ) ;
if ( SemId == -1 )
{
perror("semget");
exit(EXIT_FAILURE);
}
Arg.array[0] = 0 ;
Arg.array[1] = 0 ;
RetStat = semctl(SemId, 0, SETALL, Arg.array);
if (RetStat == -1)
{
perror("semctl");
exit(EXIT_FAILURE);
}
printf("\nPress y or Y to continue ahead.\n");
scanf("%c",&choice);
if ( ( choice != 'y') && ( choice != 'Y'))
exit(EXIT_FAILURE);
if ( ( choice != 'y') && ( choice != 'Y'))
exit(EXIT_FAILURE);
RetStat = semctl( SemId,0, SETVAL, 1 );
if( RetStat < 0 )
{
perror( "SET SEMOP Failure: " );
exit(EXIT_FAILURE);
}
return EXIT_SUCCESS ;
}
Program that waits for the semaphore set by the above program.
int DriverModule(int );
int main(int argc,char *argv[])
{
key_t SemKey = 0x12345 ;
int SemId ;
u_int Flag;
Flag = 0666 ;
SemId = semget( SemKey, 0, Flag );
if ( SemId == -1 )
{
perror("semget");
exit(EXIT_FAILURE);
}
DriverModule(SemId) ;
return EXIT_SUCCESS ;
}
#define MAX_ITERATIONS 100
struct itimerval timer;
int WaitForSemaphore(int ,unsigned short ) ;
void timer_handler (int signum)
{
static int count = 0;
printf ("timer expired %d times\n", ++count);
if ( count >= MAX_ITERATIONS ) // Stop the timer
{
printf("\n\nForcing Time Out Termination.....\n\n");
timer.it_value.tv_sec = 0;
timer.it_value.tv_usec = 0;
timer.it_interval.tv_sec = 0;
timer.it_interval.tv_usec = 0;
setitimer (ITIMER_VIRTUAL, &timer, NULL);
return ;
}
}
int DriverModule (int SemId)
{
struct sigaction sa;
/* Install timer_handler as the signal handler for SIGVTALRM. */
memset (&sa, 0, sizeof (sa));
sa.sa_flags = SA_SIGINFO;
sa.sa_handler = &timer_handler;
sigaction (SIGVTALRM, &sa, NULL);
/* Configure the timer to expire after 250 msec... */
timer.it_value.tv_sec = 0;
timer.it_value.tv_usec = 250000;
/* ... and every 500 msec after that. */
timer.it_interval.tv_sec = 0;
timer.it_interval.tv_usec = 500000;
/* Start a virtual timer. It counts down whenever this process is
executing. */
setitimer (ITIMER_VIRTUAL, &timer, NULL);
printf("\nBefore calling wait for semaphore.......\n");
// Waiting for sempahore
if( !WaitForSemaphore( SemId, 0) )
{
printf("\nUnable to get sempahore.\n");
return 0 ;
}
printf("\nAfter calling after calling wait for semaphoe module.........\n");
return 1 ;
}
int WaitForSemaphore(int SemId,unsigned short SemNum )
{
struct sembuf SemBuf;
int RetStat;
unsigned int NoOfSemOps;
SemBuf.sem_num = SemNum;
SemBuf.sem_op = -1;
SemBuf.sem_flg = 0;
NoOfSemOps = 1;
RetStat = semop( SemId, &SemBuf, NoOfSemOps );
if( RetStat < 0 )
{
if( errno == EINTR )
{
WaitForSemaphore( SemId, SemNum );
}
else
{
perror( "Wait SEMOP Failure: " );
return 0 ;
}
}
return 1 ;
}
最佳答案
好的,主要问题是使用ITIMER_VIRTUAL
。这种[类型]计数器仅在进程运行时才递减。如果进程正在执行系统调用,则该进程未运行。
因此,我们必须改用ITIMER_REAL
。而且,如果执行此操作,它将生成SIGALRM
信号[而不是SIGVTALRM
一个]。
进行这些更改之后,还有另一个问题。
必须在保护它的系统调用之后将其禁用(例如semop
)。否则,未到期的计时器(即semop
没有超时)可能会中断另一个/后续/不相关的系统调用(例如read
,write
等)。
因此,在下面的代码中,我们需要(例如):
timer_set(250000);
semop(...);
timer_set(0);
另外,请注意,可以从信号处理程序[安全地]执行有限数量的syscall [和/或库函数调用]。值得注意的是,
printf
不能在信号处理程序中使用。
errno
的原始值。
semop
之后)将看不到正确的
errno
值(例如
EINTR
),但是看不到信号处理程序选择执行的任何系统调用的
errno
值。
// create a semaphore and setting the semaphore for use by another program.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <unistd.h>
#include <stdarg.h>
#include <time.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/time.h>
#include <sys/wait.h>
int opt_n;
int opt_y;
#define MAX_ITERATIONS 100
int itype;
struct itimerval timer;
const char *pgmtail;
int WaitForSemaphore(int, unsigned short);
int DriverModule(int);
typedef long long tsc_t;
tsc_t tvzero;
tsc_t
tscget(void)
{
struct timespec ts;
tsc_t tsc;
clock_gettime(CLOCK_MONOTONIC,&ts);
tsc = ts.tv_sec;
tsc *= 1000000000;
tsc += ts.tv_nsec;
tsc -= tvzero;
return tsc;
}
double
tscsec(tsc_t tsc)
{
double sec;
sec = tsc;
sec /= 1e9;
return sec;
}
void
dbgprt(const char *fmt,...)
{
va_list ap;
char buf[1000];
char *bp = buf;
bp += sprintf(bp,"%.9f %s ",tscsec(tscget()),pgmtail);
va_start(ap,fmt);
bp += vsprintf(bp,fmt,ap);
va_end(ap);
fputs(buf,stdout);
fflush(stdout);
}
int
pgma(void)
{
key_t SemKey = 0x12345;
pgmtail = "pgma";
int SemId = -1;
int NumOfSems = 2;
int Flag = 0;
int RetStat;
#if 0
char choice = 'n';
#endif
#if 0
struct {
int val;
struct semid_ds *buf;
ushort array[2];
} Arg;
#endif
Flag |= IPC_CREAT;
//Flag |= IPC_EXCL;
Flag |= 0666;
SemId = semget(SemKey, NumOfSems, Flag);
if (SemId == -1) {
perror("semget");
exit(EXIT_FAILURE);
}
#if 0
Arg.array[0] = 0;
Arg.array[1] = 0;
RetStat = semctl(SemId, 0, SETALL, Arg.array);
if (RetStat == -1) {
perror("semctl");
exit(EXIT_FAILURE);
}
#endif
for (int phase = 0; phase <= opt_y; ++phase) {
int setval = phase;
dbgprt("pgma: SET phase=%d\n",phase);
RetStat = semctl(SemId, 0, SETVAL, setval);
if (RetStat < 0) {
perror("SET SEMOP Failure: ");
exit(EXIT_FAILURE);
}
dbgprt("USLEEP/BEF\n");
usleep(1000 * 1000);
dbgprt("USLEEP/AFT\n");
}
return EXIT_SUCCESS;
}
// Program that waits for the semaphore set by the above program.
int
pgmb(void)
{
key_t SemKey = 0x12345;
int SemId;
pgmtail = "pgmb";
// NOTE/BUG: we must add IPC_CREAT if we start pgmb first
u_int Flag = 0;
Flag |= 0666;
#if 1
Flag |= IPC_CREAT;
#endif
SemId = semget(SemKey, 2, Flag);
if (SemId == -1) {
perror("semget");
exit(EXIT_FAILURE);
}
DriverModule(SemId);
dbgprt("pgmb: complete\n");
return EXIT_SUCCESS;
}
char *
exmsg(int status)
{
static char buf[1000];
char *bp = buf;
bp += sprintf(bp,"status=[%8.8X ",status);
do {
if (WIFEXITED(status)) {
bp += sprintf(bp,"exited status=%d", WEXITSTATUS(status));
break;
}
if (WIFSIGNALED(status)) {
bp += sprintf(bp,"killed by signal %d", WTERMSIG(status));
break;
}
if (WIFSTOPPED(status)) {
bp += sprintf(bp,"stopped by signal %d", WSTOPSIG(status));
break;
}
bp += sprintf(bp,"continued");
} while (0);
bp += sprintf(bp,"]");
return buf;
}
void
testit(int newval)
{
int code;
pid_t pid;
opt_y = newval;
for (int phase = 1; phase <= 2; ++phase) {
// start the receiver
pid = fork();
if (pid != 0) {
dbgprt("testit: pid=%d\n",pid);
continue;
}
switch (phase) {
case 1:
code = pgma();
break;
case 2:
code = pgmb();
break;
default:
code = 99;
break;
}
exit(code);
}
while (1) {
int status;
pid = wait(&status);
if (pid <= 0)
break;
dbgprt("main: pid %d reaped -- %s\n",pid,exmsg(status));
}
}
int
main(int argc,char **argv)
{
//pid_t pid;
--argc;
++argv;
pgmtail = "main";
tvzero = tscget();
for (; argc > 0; --argc, ++argv) {
char *cp = *argv;
if (*cp != '-')
break;
switch (cp[1]) {
case 'n':
opt_n = ! opt_n;
break;
}
}
opt_y = ! opt_n;
dbgprt("pgma: opt_y=%d\n",opt_y);
//testit(0);
testit(1);
return 0;
}
void
timer_set(int usec)
{
dbgprt("timer_set: SET usec=%d\n",usec);
timer.it_value.tv_sec = 0;
timer.it_value.tv_usec = usec;
/* ... and every 500 msec after that. */
// NOTE/BUG: timer must _not_ be rearmed -- can abort unrelated syscalls
timer.it_interval.tv_sec = 0;
#if 0
timer.it_interval.tv_usec = 500000;
#else
timer.it_interval.tv_usec = 0;
#endif
setitimer(itype, &timer, NULL);
}
void
timer_handler(int signum)
{
static int count = 0;
// NOTE/BUG: printf may _not_ be called from a signal handler
//dbgprt("timer expired %d times\n", ++count);
// Stop the timer
// NOTE/BUG: disabling now done elsewhere
if (count >= MAX_ITERATIONS) {
//dbgprt("Forcing Time Out Termination.....\n");
timer.it_value.tv_sec = 0;
timer.it_value.tv_usec = 0;
timer.it_interval.tv_sec = 0;
timer.it_interval.tv_usec = 0;
#if 0
setitimer(ITIMER_VIRTUAL, &timer, NULL);
#else
setitimer(ITIMER_REAL, &timer, NULL);
#endif
return;
}
}
int
DriverModule(int SemId)
{
struct sigaction sa;
sigset_t set;
int signo;
#if 0
itype = ITIMER_VIRTUAL;
signo = SIGVTALRM;
#else
itype = ITIMER_REAL;
signo = SIGALRM;
#endif
/* Install timer_handler as the signal handler for SIGVTALRM. */
memset(&sa, 0, sizeof(sa));
sa.sa_flags = SA_SIGINFO;
sa.sa_handler = &timer_handler;
sigaction(signo, &sa, NULL);
sigemptyset(&set);
sigaddset(&set,signo);
sigprocmask(SIG_UNBLOCK,&set,NULL);
/* Configure the timer to expire after 250 msec... */
// Start virtual timer. It counts down whenever this process is executing.
#if 0
setitimer(itype, &timer, NULL);
#else
timer_set(250000);
#endif
dbgprt("Before calling wait for semaphore.......\n");
// Waiting for sempahore
if (! WaitForSemaphore(SemId, 0)) {
dbgprt("Unable to get sempahore.\n");
return 0;
}
dbgprt("After calling after calling wait for semaphoe module.........\n");
return 1;
}
int
WaitForSemaphore(int SemId, unsigned short SemNum)
{
struct sembuf SemBuf;
int RetStat;
unsigned int NoOfSemOps;
while (1) {
SemBuf.sem_num = SemNum;
SemBuf.sem_op = -1;
SemBuf.sem_flg = 0;
NoOfSemOps = 1;
dbgprt("WaitFor: SEMOP\n");
RetStat = semop(SemId, &SemBuf, NoOfSemOps);
if (RetStat >= 0) {
dbgprt("WaitFor: OKAY\n");
break;
}
if (errno == EINTR) {
dbgprt("WaitFor: EINTR\n");
// do stuff here ...
// rearm timer
timer_set(250000);
continue;
}
perror("Wait SEMOP Failure: ");
exit(1);
}
// NOTE/BUG: _must_ always disable timer to prevent other syscalls from being
// interrupted
#if 1
timer_set(0);
#endif
return 1;
}
0.000000332 main pgma: opt_y=1
0.000182324 main testit: pid=849558
0.000267203 main testit: pid=849559
0.000830005 pgma pgma: SET phase=0
0.000847541 pgmb timer_set: SET usec=250000
0.000882037 pgma USLEEP/BEF
0.000891077 pgmb Before calling wait for semaphore.......
0.000895977 pgmb WaitFor: SEMOP
0.250932859 pgmb WaitFor: EINTR
0.250950128 pgmb timer_set: SET usec=250000
0.250956676 pgmb WaitFor: SEMOP
0.500996272 pgmb WaitFor: EINTR
0.501014687 pgmb timer_set: SET usec=250000
0.501021903 pgmb WaitFor: SEMOP
0.751066428 pgmb WaitFor: EINTR
0.751089504 pgmb timer_set: SET usec=250000
0.751097693 pgmb WaitFor: SEMOP
1.000970921 pgma USLEEP/AFT
1.000987303 pgma pgma: SET phase=1
1.001001916 pgma USLEEP/BEF
1.001046071 pgmb WaitFor: OKAY
1.001055982 pgmb timer_set: SET usec=0
1.001062505 pgmb After calling after calling wait for semaphoe module.........
1.001066632 pgmb pgmb: complete
1.001210687 main main: pid 849559 reaped -- status=[00000000 exited status=0]
2.001078396 pgma USLEEP/AFT
2.001269995 main main: pid 849558 reaped -- status=[00000000 exited status=0]
- Why re-arming the timer is required inside
WaitForSemaphore
?
printf
调用(由于信号安全问题,我们必须这样做),作为副作用,
count
的增量无效。
printf
,没有意识到副作用“破坏了”了处理者的撤防代码。一段时间后,我意识到自己做了什么并想要这种效果(即让处理程序“什么也不做”)。
EINTR
错误-这是我们真正想要的]以外,什么也不做。
#if 0
注释掉所有代码]。
count++
)中放入 Activity /必需的代码[
printf
]。因此,
printf(...,count++);
最好是:
printf(...); count++;
这是一种体系结构选择,可以使用基准代码(非处理程序代码)来控制布/撤防。这是因为基线不知道处理程序是否做过任何事情,因此无论如何它都必须明确地进行撤防(以防止计时器/信号在等待循环代码之外触发)。
- Why
usleep
is required insidepgma
module?
pgmb
同时查看对
semop
的超时调用条件和用于测试/验证目的的正常条件。在普通/生产代码中,无需
pgma
进休眠眠状态。
pgma
将
0
值发布到信号量。然后睡眠1秒钟(1000毫秒)。
pgmb
启动时,它将看到此
0
值[和〜250毫秒后超时]。
pgmb
将以此循环约4次,直到
pgma
唤醒并发布
1
值[正常完成
pgmb
的
semop
为止]。
pgmb
来体验失败/超时情况和正常/成功情况。
semop
中
pgmb
的等待循环]对于所有可能的模式/状态都是正确的。
关于c - 在C/Linux中,计时器到期后如何执行代码发布阻止操作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63729514/
#include using namespace std; class C{ private: int value; public: C(){ value = 0;
这个问题已经有答案了: What is the difference between char a[] = ?string?; and char *p = ?string?;? (8 个回答) 已关闭
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 7 年前。 此帖子已于 8 个月
除了调试之外,是否有任何针对 c、c++ 或 c# 的测试工具,其工作原理类似于将独立函数复制粘贴到某个文本框,然后在其他文本框中输入参数? 最佳答案 也许您会考虑单元测试。我推荐你谷歌测试和谷歌模拟
我想在第二台显示器中移动一个窗口 (HWND)。问题是我尝试了很多方法,例如将分辨率加倍或输入负值,但它永远无法将窗口放在我的第二台显示器上。 关于如何在 C/C++/c# 中执行此操作的任何线索 最
我正在寻找 C/C++/C## 中不同类型 DES 的现有实现。我的运行平台是Windows XP/Vista/7。 我正在尝试编写一个 C# 程序,它将使用 DES 算法进行加密和解密。我需要一些实
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
有没有办法强制将另一个 窗口置于顶部? 不是应用程序的窗口,而是另一个已经在系统上运行的窗口。 (Windows, C/C++/C#) 最佳答案 SetWindowPos(that_window_ha
假设您可以在 C/C++ 或 Csharp 之间做出选择,并且您打算在 Windows 和 Linux 服务器上运行同一服务器的多个实例,那么构建套接字服务器应用程序的最明智选择是什么? 最佳答案 如
你们能告诉我它们之间的区别吗? 顺便问一下,有什么叫C++库或C库的吗? 最佳答案 C++ 标准库 和 C 标准库 是 C++ 和 C 标准定义的库,提供给 C++ 和 C 程序使用。那是那些词的共同
下面的测试代码,我将输出信息放在注释中。我使用的是 gcc 4.8.5 和 Centos 7.2。 #include #include class C { public:
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我的客户将使用名为 annoucement 的结构/类与客户通信。我想我会用 C++ 编写服务器。会有很多不同的类继承annoucement。我的问题是通过网络将这些类发送给客户端 我想也许我应该使用
我在 C# 中有以下函数: public Matrix ConcatDescriptors(IList> descriptors) { int cols = descriptors[0].Co
我有一个项目要编写一个函数来对某些数据执行某些操作。我可以用 C/C++ 编写代码,但我不想与雇主共享该函数的代码。相反,我只想让他有权在他自己的代码中调用该函数。是否可以?我想到了这两种方法 - 在
我使用的是编写糟糕的第 3 方 (C/C++) Api。我从托管代码(C++/CLI)中使用它。有时会出现“访问冲突错误”。这使整个应用程序崩溃。我知道我无法处理这些错误[如果指针访问非法内存位置等,
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,因为
我有一些 C 代码,将使用 P/Invoke 从 C# 调用。我正在尝试为这个 C 函数定义一个 C# 等效项。 SomeData* DoSomething(); struct SomeData {
这个问题已经有答案了: Why are these constructs using pre and post-increment undefined behavior? (14 个回答) 已关闭 6
我是一名优秀的程序员,十分优秀!