Linux系统编程(五)时序竞态

时序竞态

  • 产生原因
  • 改进
  • 总结

产生原因

#include <cstdio>
#include <stdio.h>
#include <sys/time.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <errno.h>void catch_sigalrm(int signo)
{printf("pause sucess 11111\n");
}unsigned int mysleep(unsigned int seconds)
{struct sigaction act, oldact;sigset_t new1,old;act.sa_flags = 0;act.sa_handler = catch_sigalrm;sigemptyset(&act.sa_mask);int ret=sigaction(SIGALRM, &act, &oldact);if (ret == -1){perror("sigaction error:");exit(1);}sigemptyset(&new1);sigemptyset(&old);sigaddset(&new1,SIGALRM);sigaddset(&old, SIGALRM);sigprocmask(SIG_BLOCK,&new1, NULL);sigprocmask(SIG_UNBLOCK, &old, NULL);alarm(seconds);ret=pause();//主动挂起 等信号if (ret == -1 && errno== EINTR){printf("pause sucess \n");}ret=alarm(0);sigaction(SIGALRM,&oldact,NULL);return ret;
}int main()
{mysleep(3);printf("----------------\n");return 0;
}

如果进程在执行完alarm函数后,突然失去CPU,被阻塞等待(这是有可能的,进程在执行过程中,若非原子操作,都有可能随时失去CPU),如果失去CPU的时间大于了执行完,则此时在执行pause函数前,信号已经到了,因此会先处理信号(软中断,而不是先执行pause函数),在信号处理完后,再去执行pause函数,此时进程会被永远挂起,不会被唤醒,因为SIGALRM信号已经被处理了。
时序竞态:即由于进程之间执行的顺序不同,导致同一个进程多次运行后产生了不同结果的现象。如上述sleep函数,有时执行结果是正确的,有时却会导致进程永远被挂起,因此这就是一个时序竞态问题。因此需要重新对该函数进行改进。

改进

代码如下(示例):

#include <cstdio>
#include <stdio.h>
#include <sys/time.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <errno.h>void doaction(int signo)
{printf("---------%d 信号-------\n",signo);
}int mysleep(int second)
{int unslept;struct sigaction cur, old;sigset_t n_ew,o_ld,supemask;//安装信号cur.sa_flags = 0;sigemptyset(&cur.sa_mask);cur.sa_handler = doaction;sigaction(SIGALRM,&cur, &old);//设置阻塞信号集,阻塞SIGALRM信号sigemptyset(&n_ew);sigaddset(&n_ew,SIGALRM);sigprocmask(SIG_BLOCK,&n_ew, &o_ld);//定时alarm(second);//构建一个临时的sigsuspend有效阻塞信号集supemask = o_ld;sigemptyset(&supemask);sigsuspend(&supemask);//supemask未阻塞信号挂起unslept = alarm(0);//恢复之前状态sigaction(SIGALRM,&old,NULL);sigprocmask(SIG_SETMASK,&o_ld,NULL);return unslept;//int ret=pause();//if (ret == -1 && errno == EINTR)//{//	printf("pause success\n");//}}int main()
{mysleep(3);}

使用sigsuspend函数,sigsuspend具有“原子操作“,这样就能够避免。

总结

  • 竞态条件,跟系统负载有很紧密的关系,体现出信号的不可靠性。系统负载越严重,信号不可靠性越强。
  • 不可靠由其实现原理所致。信号是通过软件方式实现(跟内核调度高度依赖,延时性强),每次系统调用结束后,或中断处理处理结束后,需通过扫描PCB中的未决信号集,来判断是否应处理某个信号。当系统负载过重时,会出现时序混乱。
  • 这种意外情况只能在编写程序过程中,提早预见,主动规避,而无法通过gdb程序调试等其他手段弥补。且由于该错误不具规律性,后期捕捉和重现十分困难。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/384408.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux C++ 简单爬虫

转载&#xff1a;http://blog.csdn.net/orthocenterchocolate/article/details/38665937 方便易用&#xff0c;传入URL&#xff0c;返回对应页面的内容 [cpp] view plaincopy #include <iostream> #include <string> #include <netdb.h> #include <…

Linux系统编程(六)守护进程

Linux系统编程&#xff08;六&#xff09;守护进程一、进程组概念二、会话创建会话的条件守护进程概念守护进程模型创建守护进程一、进程组 概念 进程组&#xff0c;也称之为作业。代表一个或多个进程的集合。每个进程都属于一个进程组。 当父进程&#xff0c;创建子进程的时…

TCP 客户端和服务器端

转自&#xff1a;http://blog.csdn.net/itcastcpp/article/details/39047265 前面几篇中实现的client每次运行只能从命令行读取一个字符串发给服务器&#xff0c;再从服务器收回来&#xff0c;现在我们把它改成交互式的&#xff0c;不断从终端接受用户输入并和server交互。 [cp…

利用多线程实现linux下C语言的聊天室程序:

转载&#xff1a;http://www.360doc.com/content/16/0421/11/478627_552531090.shtml 利用多线程实现linux下C语言的聊天室程序&#xff1a; 客户端代码&#xff1a; threadsend线程负责客户端消息的发送&#xff1b; threadrecv线程负责客户端接受服务器端的消息。 [html] v…

Linux系统编程(七)消息队列

Linux系统编程&#xff08;七&#xff09;消息队列一、什么是消息队列二、消息队列内部原理三、实现消息队列的收发1.发送消息队列2.接收消息队列四、消息队列与命名管道的比较一、什么是消息队列 消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法。每个数据块都…

基于Linux的SOCKET编程之TCP半双工Client-Server聊天程序

转自&#xff1a;http://blog.csdn.net/apollon_krj/article/details/53398448#0-tsina-1-64987-397232819ff9a47a7b7e80a40613cfe1 所谓半双工通信&#xff0c;即通信双方都可以实现接发数据&#xff0c;但是有一个限制&#xff1a;只能一方发一方收&#xff0c;之后交换收发对…

Linux系统编程(八)线程

Linux系统编程&#xff08;八&#xff09;线程一、什么是线程&#xff1f;二、Linux内核线程实现原理线程共享资源线程非共享资源线程优缺点线程控制原语一、什么是线程&#xff1f; LWP&#xff1a;light weight process 轻量级的进程&#xff0c;本质仍是进程(在Linux环境下…

智能算法(GA、DBO等)求解阻塞流水车间调度问题(BFSP)

先做一个声明&#xff1a;文章是由我的个人公众号中的推送直接复制粘贴而来&#xff0c;因此对智能优化算法感兴趣的朋友&#xff0c;可关注我的个人公众号&#xff1a;启发式算法讨论。我会不定期在公众号里分享不同的智能优化算法&#xff0c;经典的&#xff0c;或者是近几年…

Linux socket编程,对套接字进行封装

转自&#xff1a;http://www.cnblogs.com/-Lei/archive/2012/09/04/2670942.html 下面是对socket操作的封装&#xff0c;因为在Linux下写中文到了windows里面会乱码&#xff0c;所以注释用英文来写&#xff0c;有空再查下解决方法吧 socket.h #ifndef SOCKET_H #define SOCKET_…

Linux系统编程(九)线程同步

Linux系统编程&#xff08;九&#xff09;线程同步一、什么是线程同步&#xff1f;二、互斥量三、条件变量pthread_cond_wait函数pthread_cond_signal函数生产者和消费者模型一、什么是线程同步&#xff1f; 线程同步&#xff0c;指一个线程发出某一功能调用时&#xff0c;在没…

linux网络编程(一)网络基础传输知识

linux网络编程&#xff08;一&#xff09;网络传输基础知识一、什么是协议&#xff1f;二、使用步骤典型协议2.网络应用程序设计模式C/S模式B/S模式优缺点3.分层模型4.TCP/IP四层模型通信过程5.协议格式数据包封装以太网帧格式ARP数据报格式IP段格式UDP数据报格式TCP数据报格式…

linux网络编程:使用多进程实现socket同时收发数据

转载&#xff1a;http://blog.csdn.net/li_wen01/article/details/52685844 前面已讲过使用一个进程实现服务端和客户端P2P通信的实例&#xff0c;但是它只能同时处理一个客户端的连接。如果要实现并发处理多个客户端的连接并且实现P2P通信&#xff0c;可以使用多进程来处理。相…

Linux 进程学习(四)------ sigaction 函数

转自&#xff1a;http://www.cnblogs.com/wblyuyang/archive/2012/11/13/2768923.html 使用 sigaction 函数&#xff1a; signal 函数的使用方法简单&#xff0c;但并不属于 POSIX 标准&#xff0c;在各类 UNIX 平台上的实现不尽相同&#xff0c;因此其用途受 到了一定的限制…

linux网络编程(二)高并发服务器

linux网络编程&#xff08;二&#xff09;高并发服务器错误处理高并发服务器多进程并发服务器客户端错误处理 #include "wrap.h"int Bind(int fd, const struct sockaddr* sa, socklen_t salen) {int ret;if ((ret bind(fd, sa, salen)) < 0){perror("bind…

linux知识(一) 程序、进程与线程

linux知识&#xff08;一&#xff09; 程序、进程与线程程序进程程序如何变成进程&#xff1f;线程线程与进程fork和创建新线程的区别优点程序 程序&#xff1a;程序是已编译好的二进制文件&#xff0c;存储在磁盘中&#xff0c;不占用系统资源 程序包括&#xff1a; RO段&am…

linux 信号signal和sigaction理解

转载&#xff1a;http://blog.csdn.net/beginning1126/article/details/8680757 今天看到unp时发现之前对signal到理解实在浅显&#xff0c;今天拿来单独学习讨论下。 signal&#xff0c;此函数相对简单一些&#xff0c;给定一个信号&#xff0c;给出信号处理函数则可&#xff…

linux知识(二)互斥量、信号量和生产者消费者模型

linux知识&#xff08;二&#xff09;互斥量、信号量和生产者消费者模型一、互斥量产生原因二、信号量生产者消费者模型一、互斥量 产生原因 使用多线程常常会碰到数据混乱的问题&#xff0c;那么使用互斥量&#xff0c;相当于“加锁”的操作&#xff0c;将有助于解决数据混乱…

基于Linux的Socket编程之TCP全双工Server-Client聊天程序

转载&#xff1a;http://blog.csdn.net/apollon_krj/article/details/53437764#0-tsina-1-58570-397232819ff9a47a7b7e80a40613cfe1 一、引言&#xff1a; 由于accept函数、read、write、recv、send等函数都是是阻塞式的&#xff0c;在同一个进程之中&#xff0c;只要有任何一个…

数据结构(一)线性表

数据结构&#xff08;一&#xff09;线性表一、线性表定义二、顺序表定义动态数组三、单链表定义不带头结点带头结点头结点与不带头结点的区别头插法与尾插法双链表循环链表循环单链表循环双链表静态链表一、线性表定义 线性表是具有相同数据类型的n个数据元素的有限序列 特点…

linux网络编程(二)TCP通讯状态

linux网络编程&#xff08;二&#xff09;TCP通讯状态TCP状态转换为什么需要等待2MSL&#xff1f;端口复用TCP状态转换 tcp协议连接开始会经过三次握手&#xff0c;客户端和服务器开始都会处于CLOSED状态 第一次握手&#xff1a;客户端会先发送SYN请求给服务器&#xff0c;客户…