• 关于 signal()函数 的搜索结果

回答

在对上面的例子作分析之前,我们需要了解C语言的声明优先级,《C专家编程》P64原文如下:image规则A规定了要按照优先级来解释声明(算是一句废话)。规则C请参照本人上一篇笔记:http://www.cnblogs.com/deyuanqin/p/5705967.html。规则B的具体实践过程如下图:image本着抛砖引玉的目的,我们使用以上规则分析void (signal(int sig, void (handler)(int)))(int)这个复杂的声明。从易到难的顺序:void (*handler)(int):① handler右边是圆括号,所以handler不是数组或者函数。再看其左边,是(星号),所以handler是一个指向*的指针。② (handler)(int)。(handler)的右边是圆括号,因而(handler)(int)中的()(int)是一个返回的函数。结合上一步分析,handler是一个指向返回*的函数的指针。③ (*handler)(int)的右边没有符号,左边是void。综上,handler是一个指向返回void值的函数的指针。void (signal(int sig, void (handler)(int)))(int):void (handler)(int)在上面的步骤已经做了分析,我们可以使用语句typedef void (handler)(int)将其简化(将handler声明为一个新的类型,这个类型是是一个指向返回void值的函数的指针。有关typedef的知识改日再做分析),则void (signal(int sig, void (handler)(int)))(int)就被简化为void (signal(int sig, handle h))(int)。下面我们对void (signal(int sig, handle h))(int)作分析:① signal右边是圆括号,因而signal()是一个返回**的函数。② signal()的左边是,因而signal()是一个返回指向*的指针的函数。③ (signal(int sig, handle h))右边是圆括号,因此(signal(int sig, handle h))(int)是一个返回的函数。综上,signal是一个返回指向返回函数的指针的函数。④ (*signal(int sig, handle h))右边是void。因而,signal(这个标识符)是一个返回指向返回void值的函数的指针的函数。以上的分析过程可能有错漏,请各位看官多指教。

一生有你llx 2019-12-02 02:39:17 0 浏览量 回答数 0

回答

在对上面的例子作分析之前,我们需要了解C语言的声明优先级,《C专家编程》P64原文如下:image规则A规定了要按照优先级来解释声明(算是一句废话)。规则C请参照本人上一篇笔记:http://www.cnblogs.com/deyuanqin/p/5705967.html。规则B的具体实践过程如下图:image本着抛砖引玉的目的,我们使用以上规则分析void (signal(int sig, void (handler)(int)))(int)这个复杂的声明。从易到难的顺序:void (*handler)(int):① handler右边是圆括号,所以handler不是数组或者函数。再看其左边,是(星号),所以handler是一个指向*的指针。② (handler)(int)。(handler)的右边是圆括号,因而(handler)(int)中的()(int)是一个返回的函数。结合上一步分析,handler是一个指向返回*的函数的指针。③ (*handler)(int)的右边没有符号,左边是void。综上,handler是一个指向返回void值的函数的指针。void (signal(int sig, void (handler)(int)))(int):void (handler)(int)在上面的步骤已经做了分析,我们可以使用语句typedef void (handler)(int)将其简化(将handler声明为一个新的类型,这个类型是是一个指向返回void值的函数的指针。有关typedef的知识改日再做分析),则void (signal(int sig, void (handler)(int)))(int)就被简化为void (signal(int sig, handle h))(int)。下面我们对void (signal(int sig, handle h))(int)作分析:① signal右边是圆括号,因而signal()是一个返回**的函数。② signal()的左边是,因而signal()是一个返回指向*的指针的函数。③ (signal(int sig, handle h))右边是圆括号,因此(signal(int sig, handle h))(int)是一个返回的函数。综上,signal是一个返回指向返回函数的指针的函数。④ (*signal(int sig, handle h))右边是void。因而,signal(这个标识符)是一个返回指向返回void值的函数的指针的函数。以上的分析过程可能有错漏,请各位看官多指教。

xumaojun 2019-12-02 02:39:16 0 浏览量 回答数 0

回答

在对上面的例子作分析之前,我们需要了解C语言的声明优先级,《C专家编程》P64原文如下:image规则A规定了要按照优先级来解释声明(算是一句废话)。规则C请参照本人上一篇笔记:http://www.cnblogs.com/deyuanqin/p/5705967.html。规则B的具体实践过程如下图:image本着抛砖引玉的目的,我们使用以上规则分析void (signal(int sig, void (handler)(int)))(int)这个复杂的声明。从易到难的顺序:void (*handler)(int):① handler右边是圆括号,所以handler不是数组或者函数。再看其左边,是(星号),所以handler是一个指向*的指针。② (handler)(int)。(handler)的右边是圆括号,因而(handler)(int)中的()(int)是一个返回的函数。结合上一步分析,handler是一个指向返回*的函数的指针。③ (*handler)(int)的右边没有符号,左边是void。综上,handler是一个指向返回void值的函数的指针。void (signal(int sig, void (handler)(int)))(int):void (handler)(int)在上面的步骤已经做了分析,我们可以使用语句typedef void (handler)(int)将其简化(将handler声明为一个新的类型,这个类型是是一个指向返回void值的函数的指针。有关typedef的知识改日再做分析),则void (signal(int sig, void (handler)(int)))(int)就被简化为void (signal(int sig, handle h))(int)。下面我们对void (signal(int sig, handle h))(int)作分析:① signal右边是圆括号,因而signal()是一个返回**的函数。② signal()的左边是,因而signal()是一个返回指向*的指针的函数。③ (signal(int sig, handle h))右边是圆括号,因此(signal(int sig, handle h))(int)是一个返回的函数。综上,signal是一个返回指向返回函数的指针的函数。④ (*signal(int sig, handle h))右边是void。因而,signal(这个标识符)是一个返回指向返回void值的函数的指针的函数。以上的分析过程可能有错漏,请各位看官多指教。

nothingfinal 2019-12-02 02:39:17 0 浏览量 回答数 0

新用户福利专场,云服务器ECS低至102元/年

新用户专场,1核2G 102元/年起,2核4G 699.8元/年起

回答

void (signal(int sig, void (handler)(int)))(int); ^^^^^^^^^^^^^^^^^^^^^ // 是函数指针,设为 Func1void (*signal(int sig, Func1))(int) ^^^^^^^^^^^^^^^^^^^^^^ // 是普通函数,设为 Func2void (*Func2)(int)^^^^^^^^^^^^^^^^^^// 是函数指针,设为 Func3Func1: void(*)(int)Func2: signal(int, Func1)Func3: void(*)(int) == Func1于是该函数声明可简化为:Func1 signal(int, Func1);还觉得难吗?再补充上用法吧,可能更加清楚:void my_handler (int param){ signaled = 1;}void (*prev_handler)(int); // 声明一个函数指针prev_handler = signal (SIGINT, my_handler); 应该很清楚了,该函数声明中,主体是 Func2, 返回值与参数 2 的类型都是 Func1.

a123456678 2019-12-02 02:39:16 0 浏览量 回答数 0

问题

使用signal函数无法编译通过,已经包含signal.h头文件

a123456678 2019-12-01 19:57:28 1382 浏览量 回答数 1

问题

迷惑?Qt槽函数不是立即被执行的吗?

杨冬芳 2019-12-01 20:23:52 1064 浏览量 回答数 1

问题

C语言高手帮忙分析一下复杂的函数声明

a123456678 2019-12-01 19:48:34 1161 浏览量 回答数 7

问题

QT怎么快速实现走动棋子

a123456678 2019-12-01 20:11:06 903 浏览量 回答数 1

问题

求教,怎么实现QListWidget的item设置成只识别鼠标左键点击 :报错

kun坤 2020-06-14 17:01:07 0 浏览量 回答数 1

回答

看起来你对过滤器功能应该做什么有一点误解。它Traceroute从返回的数据集中过滤整个对象false。你需要做的是编写一个map函数,它将原始Traceroute对象转换为所需的对象。下面是如何执行此操作的示例Dataset[Traceroute] 首先,您需要稍微修改您的案例类,如下所示。 case class Result(var result: Seq[Signal], hop: Int) case class Signal(rtt: Double, from: String) case class Traceroute( dst_name: String, from: String, prb_id: BigInt, msm_id: BigInt, timestamp: BigInt, result: Seq[Result]) 正如你可以看到我已经添加var到result的领域Result类。这将有助于我们result稍后在自定义函数中修改字段,我们将传递给地图操作 然后定义以下两个函数,如下所示: def checkSignal(signal: Signal): Boolean = { if (signal.rtt > 0) { return true } else { return false } } def removeNegative(traceroute: Traceroute): Traceroute = { val outerList = traceroute.result for( temp <- outerList){ val innerList = temp.result //here we are filtering the list to only contain nonnegative elements val newinnerList = innerList.filter(checkSignal(_)) //here we are reassigning the newlist to result temp.result = newinnerList } traceroute }现在,我们将从已转换的数据集中映射原始数据集,我们正确地接收过滤列表。 val dataPath = "hdfs/path/to/traceroute.json"val tracerouteSchema = ScalaReflection.schemaFor[Traceroute].dataType.asInstanceOf[StructType]val dataset = spark.read.schema(tracerouteSchema).json(dataPath).as[Traceroute] println("Showing 10 rows of original Dataset")dataset.show(10, truncate = false) val maprtts = dataset.map(x => removeNegative(x)) println("Showing 10 rows of transformed dataset")maprtts.show(10, truncate = false)以下是输出: Showing 10 rows of original dataset dst_name from prb_id msm_id timestamp result null null null null 1514768409 [[[[1.955, 89.105.200.57]], 1]] null null null null 1514768402 [[[[-2.5, 89.105.200.57], [19.955, 89.105.200.57]], 2]] Showing 10 rows of transformed dataset dst_name from prb_id msm_id timestamp result null null null null 1514768409 [[[[1.955, 89.105.200.57]], 1]] null null null null 1514768402 [[[[19.955, 89.105.200.57]], 2]]

社区小助手 2019-12-02 01:47:59 0 浏览量 回答数 0

回答

解决如下: #include <stdio.h> #include <stdlib.h> #include <string.h> #include <pthread.h> #include <semaphore.h> #define SIZE 1024 #define TIMER 5 #define LENTH 4 char buffer[SIZE]; pthread_mutex_t mutex; //设置初始化互斥量 pthread_cond_t cond = PTHREAD_COND_INITIALIZER; //设置线程挂起和回复的条件变量 void *thread_play_0(void *arg); void Error_print(int num,char *pStr) //封装一个检测函数,主要检测线程的建立等一系列操作是否正确 { if(num != 0) { perror(pStr); exit(EXIT_FAILURE); } } int main(void) { int ret; pthread_t id; //创建线程 pthread_attr_t thread_attr; //设置线程属性 ret = pthread_attr_init(&thread_attr); Error_print(ret,"Init error\n"); ret = pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED); //设线程属性为脱离,线程结束后不需要返回,能在后台与主线同时执行 Error_print(ret,"Init error\n"); ret = pthread_mutex_init(&mutex,NULL); Error_print(ret,"Init error\n"); ret = pthread_create(&id, &thread_attr,thread_play_0,NULL); Error_print(ret,"Create error\n"); while(scanf("%s",buffer)) { //设置恢复和退出条件 if(strncmp("stop",buffer,LENTH) == 0) { //退出 pthread_mutex_lock(&mutex); printf("-------Goodbye-------\n"); sleep(1); break; } if(strncmp("start",buffer,TIMER) == 0) { //恢复线程 pthread_mutex_lock(&mutex); pthread_cond_signal(&cond); pthread_mutex_unlock(&mutex); sleep(1); } } exit(EXIT_SUCCESS); } void *thread_play_0(void *arg) //线程执行函数 { while (1) { pthread_mutex_lock(&mutex); //循环打印 printf("It's a flash,input stop to stop,input pause to pause.\n"); pthread_mutex_unlock(&mutex); sleep(1); if (strncmp("stop", buffer, LENTH) == 0) { //退出线程 break; } if (strncmp("pause", buffer, TIMER) == 0) { //挂起线程 strcpy(buffer," "); pthread_mutex_lock(&mutex); printf("---------Flash is paused---------\n"); printf("Input start to play the flash again.\n"); pthread_cond_wait(&cond,&mutex); pthread_mutex_unlock(&mutex); } } pthread_exit(NULL); }

杨冬芳 2019-12-02 02:27:29 0 浏览量 回答数 0

回答

@吥楛糖 ,求指导,谢谢######继承QLineEdit,派生类里实现 mousePressEvent或者mouseReleaseEvent函数就行了  ###### 用selectionChanged信号 或 重写focusInEvent 事件 或 mousePressEvent 事件 ######这个你可以自己做一个信号槽的,自定义一下槽和信号就好了。 如果你想要实现鼠标一放进去就响应clicked()的话,可以在QLineEdit的派生类的keyPressEvent()里发送一个信号出去######qMyEdit.h #ifndef QMYEDIT_H #define QMYEDIT_H #include <QtGui> class QMyEdit : public QLineEdit { Q_OBJECT public: explicit QMyEdit(QWidget *parent = 0); protected: virtual void mousePressEvent(QMouseEvent *event); private slots: signals: void LineEditClicked(); }; #endif // QMYEDIT_H qMyEdit.cpp #include "qmyedit.h" QMyEdit::QMyEdit(QWidget *parent) : QLineEdit(parent) { } void QMyEdit::mousePressEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) { emit LineEditClicked(); } QLineEdit::mousePressEvent(event); } mainWindow.h #include "qmyedit.h" namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); private slots: void myEditClicked(); private: Ui::MainWindow *ui; QMyEdit *pMyEdit; }; #endif // MAINWINDOW_H mainWindow.cpp #include "mainwindow.h" #include "ui_mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); ui->lineEdit->setVisible(false); pMyEdit = new QMyEdit(this); QRect rect = ui->lineEdit->geometry(); pMyEdit->setGeometry(rect); connect(pMyEdit, SIGNAL(LineEditClicked()), this, SLOT(myEditClicked())); } MainWindow::~MainWindow() { delete ui; } void MainWindow::myEditClicked() { qDebug() << "clicked!!!"; } ###### 引用来自“吥楛糖”的答案 qMyEdit.h #ifndef QMYEDIT_H #define QMYEDIT_H #include <QtGui> class QMyEdit : public QLineEdit { Q_OBJECT public: explicit QMyEdit(QWidget *parent = 0); protected: virtual void mousePressEvent(QMouseEvent *event); private slots: signals: void LineEditClicked(); }; #endif // QMYEDIT_H qMyEdit.cpp #include "qmyedit.h" QMyEdit::QMyEdit(QWidget *parent) : QLineEdit(parent) { } void QMyEdit::mousePressEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) { emit LineEditClicked(); } QLineEdit::mousePressEvent(event); } mainWindow.h #include "qmyedit.h" namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); private slots: void myEditClicked(); private: Ui::MainWindow *ui; QMyEdit *pMyEdit; }; #endif // MAINWINDOW_H mainWindow.cpp #include "mainwindow.h" #include "ui_mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); ui->lineEdit->setVisible(false); pMyEdit = new QMyEdit(this); QRect rect = ui->lineEdit->geometry(); pMyEdit->setGeometry(rect); connect(pMyEdit, SIGNAL(LineEditClicked()), this, SLOT(myEditClicked())); } MainWindow::~MainWindow() { delete ui; } void MainWindow::myEditClicked() { qDebug() << "clicked!!!"; } 真是太谢谢你了,离成功差一步,我的理解还是不够清楚,谢谢

kun坤 2020-06-10 09:22:10 0 浏览量 回答数 0

问题

绘制scalogram如何选择级别在contourf

kun坤 2019-12-30 09:30:31 0 浏览量 回答数 0

回答

实际上mysql链接作为一个资源,在其创建的时候就被绑上了一个"destructor":php-5.2.17/ext/mysql/php_mysql.c全选复制放进笔记//386行 ZEND_MODULE_STARTUP_D(mysql) { REGISTER_INI_ENTRIES(); le_result = zend_register_list_destructors_ex(_free_mysql_result, NULL, "mysql result", module_number); le_link = zend_register_list_destructors_ex(_close_mysql_link, NULL, "mysql link", module_number); .... } //308行 static void _close_mysql_link(zend_rsrc_list_entry *rsrc TSRMLS_DC) { php_mysql_conn *link = (php_mysql_conn *)rsrc->ptr; void (*handler) (int); handler = signal(SIGPIPE, SIG_IGN); mysql_close(&link->conn); signal(SIGPIPE, handler); efree(link); MySG(num_links)--; } 当php脚本结束时,所有的资源会被释放,包括未被关闭的mysql的链接,这时候就会执行_close_mysql_link,关闭对应的链接(注:使用mysql_pconnect创建的链接另当别论)。如果你希望在php结束的时候自动关闭,可以使用 register_shutdown_function 这个php内建函数。不过参考上面的内容,这么做没有意义。最后,实际上要求使用mysql_close只是为了优化,如果你的应用请求数很多,用完mysql以后及时关闭,能够避免一些可能的问题

蛮大人123 2019-12-02 01:43:20 0 浏览量 回答数 0

问题

关于linux c语言多线程编程的问题

杨冬芳 2019-12-01 20:25:21 1031 浏览量 回答数 2

问题

linux下的C程序内存泄露问题:报错

kun坤 2020-06-07 16:27:10 0 浏览量 回答数 1

回答

void statistics(int signo) { printf("\n--------------------PING statistics-------------------\n"); printf("%d packets transmitted, %d received , %d%% lost\n", nsend,nreceived,(nsend-nreceived)/nsend*100); close(sockfd); exit(1); } /*校验和算法*/ unsigned short cal_chksum(unsigned short *addr,int len) { int nleft=len; int sum=0; unsigned short *w=addr; unsigned short answer=0; /*把ICMP报头二进制数据以2字节为单位累加起来*/ while(nleft>1) { sum+=*w++; nleft-=2; } /*若ICMP报头为奇数个字节,会剩下最后一字节。把最后一个字节视为一个2字节数据的高 //字节,这个2字节数据的低字节为0,继续累加*/ if( nleft==1) { *(unsigned char *)(&answer)=*(unsigned char *)w; sum+=answer; } sum=(sum>>16)+(sum&0xffff); sum+=(sum>>16); answer=~sum; return answer; } /*设置ICMP报头*/ int pack(int pack_no) { int i,packsize; struct icmp *icmp; struct timeval *tval; icmp=(struct icmp*)sendpacket; icmp->icmp_type=ICMP_ECHO; icmp->icmp_code=0; icmp->icmp_cksum=0; icmp->icmp_seq=pack_no; icmp->icmp_id=pid; packsize=8+datalen; tval= (struct timeval *)icmp->icmp_data; gettimeofday(tval,NULL); /*记录发送时间*/ icmp->icmp_cksum=cal_chksum( (unsigned short *)icmp,packsize); /*校验算法*/ return packsize; } /*发送三个ICMP报文*/ void send_packet() { int packetsize; while( nsend<MAX_NO_PACKETS) //发送MAX_NO_PACKETS个ICMP报文 { nsend++; packetsize=pack(nsend); /*设置ICMP报头*/ //sendpacket为要发送的内容,由pack()函数设定,dest_addr是目的地址, if( sendto(sockfd,sendpacket,packetsize,0, (struct sockaddr *)&dest_addr,sizeof(dest_addr) )<0 ) { perror("sendto error"); continue; } sleep(1); /*每隔一秒发送一个ICMP报文*/ } } /*接收所有ICMP报文*/ void recv_packet() { int n,fromlen; extern int errno; signal(SIGALRM,statistics); fromlen=sizeof(from); while( nreceived<nsend) { //alarm()用来设置信号SIGALRM在经过参数seconds指定的秒数后传送给目前的进程 alarm(MAX_WAIT_TIME); if( (n=recvfrom(sockfd,recvpacket,sizeof(recvpacket),0, (struct sockaddr *)&from,&fromlen)) <0) { if(errno==EINTR) continue; perror("recvfrom error"); continue; } gettimeofday(&tvrecv,NULL); /*记录接收时间*/ if(unpack(recvpacket,n)==-1)continue; nreceived++; } } /*剥去ICMP报头*/ int unpack(char *buf,int len) { int i,iphdrlen; struct ip *ip; struct icmp *icmp; struct timeval *tvsend; double rtt; ip=(struct ip *)buf; //求ip报头长度,即ip报头的长度标志乘4,头长度指明头中包含的4字节字的个数。可接受 //的最小值是5,最大值是15 iphdrlen=ip->ip_hl<<2; icmp=(struct icmp *)(buf+iphdrlen); /*越过ip报头,指向ICMP报头*/ len-=iphdrlen; /*ICMP报头及ICMP数据报的总长度*/ if( len<8) /*小于ICMP报头长度则不合理*/ { printf("ICMP packets\'s length is less than 8\n"); return -1; } /*确保所接收的是我所发的的ICMP的回应*/ if( (icmp->icmp_type==ICMP_ECHOREPLY) && (icmp->icmp_id==pid) ) { tvsend=(struct timeval *)icmp->icmp_data; tv_sub(&tvrecv,tvsend); /*接收和发送的时间差*/ rtt=tvrecv.tv_sec*1000+tvrecv.tv_usec/1000; /*以毫秒为单位计算rtt*/ /*显示相关信息*/ printf("%d byte from %s: icmp_seq=%u ttl=%d rtt=%.3f ms\n", len,inet_ntoa(from.sin_addr),icmp->icmp_seq,ip->ip_ttl,rtt); } else return -1; } int main(int argc,char *argv[]) { struct hostent *host; struct protoent *protocol; unsigned long inaddr=0l; int waittime=MAX_WAIT_TIME; //#define MAX_WAIT_TIME 5 int size=50*1024; if(argc<2) { printf("usage:%s hostname/IP address\n",argv[0]); exit(1); } //getprotobyname("icmp")返回对应于给定协议名的包含名字和协议号的protoent结构指针。 if( (protocol=getprotobyname("icmp") )==NULL) { perror("getprotobyname"); exit(1); } /*生成使用ICMP的原始套接字,这种套接字只有root才能生成*/ if( (sockfd=socket(AF_INET,SOCK_RAW,protocol->p_proto) )<0) { perror("socket error"); exit(1); } /* 回收root权限,设置当前用户权限*/ setuid(getuid()); /*扩大套接字接收缓冲区到50K这样做主要为了减小接收缓冲区溢出的 的可能性,若无意中ping一个广播地址或多播地址,将会引来大量应答*/ setsockopt(sockfd,SOL_SOCKET,SO_RCVBUF,&size,sizeof(size) ); bzero(&dest_addr,sizeof(dest_addr)); dest_addr.sin_family=AF_INET; /*判断是主机名还是ip地址*/ if( inaddr=inet_addr(argv[1])==INADDR_NONE) { if((host=gethostbyname(argv[1]) )==NULL) /*是主机名*/ { perror("gethostbyname error"); exit(1); } memcpy( (char *)&dest_addr.sin_addr,host->h_addr,host->h_length); } else /*是ip地址*/ dest_addr.sin_addr.s_addr = inet_addr(argv[1]); /*获取main的进程id,用于设置ICMP的标志符*/ pid=getpid(); printf("PING %s(%s): %d bytes data in ICMP packets.\n",argv[1], inet_ntoa(dest_addr.sin_addr),datalen); send_packet(); /*发送所有ICMP报文*/ recv_packet(); /*接收所有ICMP报文*/ statistics(SIGALRM); /*进行统计*/ return 0; } /*两个timeval结构相减*/ void tv_sub(struct timeval *out,struct timeval *in) { if( (out->tv_usec-=in->tv_usec)<0) { --out->tv_sec; out->tv_usec+=1000000; } out->tv_sec-=in->tv_sec;

云栖技术 2019-12-02 02:35:16 0 浏览量 回答数 0

回答

你既然用到了锁,那么你解锁的过程呢?我只看到了加锁啊!目前,看不出来其他的地方还有什么问题######void put(const T& x) { { ScopeMutexLock lock(m_mutex); LOG_DEBUG("Queue, put data\n"); m_queue.push_back(x); LOG_DEBUG("Queue, aftet push_back,size :%ld\n", m_queue.size()); } m_notEmpty.notify(); } T get() { ScopeMutexLock lock(m_mutex); while (m_queue.empty()) { printf("Queue,in wait\n"); m_notEmpty.wait(); } LOG_DEBUG("Queue,after wait, will get data\n"); //assert(!m_Queue.empty()); T front(m_queue.front()); m_queue.pop_front(); return front; } notify之前就需要把m_mutex unlock,因为wait函数内部会先unlock再block锁,所以你notify之前不释放锁的话,就会死锁。 Reference: http://www.cnblogs.com/ngnetboy/p/3521547.html ######看不出代码有问题, 把你导致死锁的测试代码贴出来看看。######为什么不在进程里面读队列,之后分配给线程去处理,只要管理好线程的反馈就可以了。######void put(const T& x) { ScopeMutexLock lock(m_mutex); LOG_DEBUG("Queue, put data\n"); bool need_notify = m_queue.empty(); m_queue.push_back(x); LOG_DEBUG("Queue, aftet push_back,size :%ld\n", m_queue.size()); if(need_notify){ m_notEmpty.notify(); } } T get() { ScopeMutexLock lock(m_mutex); while(m_queue.empty()) { printf("Queue,in wait\n"); 添加 unlock(m_mutex); m_notEmpty.wait(); 重新加锁 lock(m_mutex); } LOG_DEBUG("Queue,after wait, will get data\n"); //assert(!m_Queue.empty()); T front(m_queue.front()); m_queue.pop_front(); return front; } ###### 谢谢各位解答:改为这样已经好,但是如果还用之前的ScopeMutexLock lock(m_mutex) 把notify 放在调用完put的地方调用一遍还是不行         void put(const T& x)         {                 //printf("queue will lock b put:%p\n",m_mutex.getMutex());                 //ScopeMutexLock lock(m_mutex);                 m_lock->lock();                 printf("Queue, before put data!!!!\n");                 m_queue.push_back(x);                 printf("Queue, aftet put data!!!,size :%ld\n", m_queue.size());                 m_lock->unlock();                 m_notEmpty.notify();         }         T get()         {                 //printf("queue will lock b get!!!!:%p\n",m_mutex.getMutex());                 //ScopeMutexLock lock(m_mutex);                 m_lock->lock();                 printf("Queue,before get!!!,size:%ld\n",m_queue.size());                 while (m_queue.empty())                 {                         printf("Queue,in wait!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");                         m_notEmpty.wait();                 }                 printf("Queue,after wait!!!!, will get data,queue size:%ld\n",m_queue.size());                 m_lock->unlock();                 //assert(!m_Queue.empty());                 T front(m_queue.front());                 m_queue.pop_front();                 return front;         } ###### 看这个,经典实现 https://github.com/chenshuo/muduo/blob/master/muduo/base/BlockingQueue.h C++ 2011 ######这个不行的,我之前设计的跟他的一样。。。###### 引用来自“hzh62”的评论 看这个,经典实现 https://github.com/chenshuo/muduo/blob/master/muduo/base/BlockingQueue.h C++ 2011 这个怎么不行,完全线程安全。。。 一个锁,两个条件变量的经典实现。 几行代码,又简单,又清晰。 ######回复 @hzh62 : 看了下资料,你说的在理,虽然问题改好了,但现在认为不是signal的位置导致,准备再跟踪下######回复 @grane : lock 后,unlock 前 发 nodify,这样更安全######看他的put函数,push_back之后 notEmpty_.notify();是在lock之后unlock之前的,这个信号发不出去,必须在unlock之后执行notify,我的测试结果是这样的######要用锁加信号而已。

kun坤 2020-06-08 19:21:14 0 浏览量 回答数 0

回答

threading 库可以在单独的线程中执行任何的在 Python 中可以调用的对象。你可以创建一个 Thread 对象并将你要执行的对象以 target 参数的形式提供给该对象。 下面是一个简单的例子: # Code to execute in an independent thread import time def countdown(n): while n > 0: print('T-minus', n) n -= 1 time.sleep(5) # Create and launch a thread from threading import Thread t = Thread(target=countdown, args=(10,)) t.start() 当你创建好一个线程对象后,该对象并不会立即执行,除非你调用它的 start() 方法(当你调用 start() 方法时,它会调用你传递进来的函数,并把你传递进来的参数传递给该函数)。Python中的线程会在一个单独的系统级线程中执行(比如说一个 POSIX 线程或者一个 Windows 线程),这些线程将由操作系统来全权管理。线程一旦启动,将独立执行直到目标函数返回。你可以查询一个线程对象的状态,看它是否还在执行: if t.is_alive(): print('Still running') else: print('Completed') 你也可以将一个线程加入到当前线程,并等待它终止: t.join() Python解释器直到所有线程都终止前仍保持运行。对于需要长时间运行的线程或者需要一直运行的后台任务,你应当考虑使用后台线程。 例如: t = Thread(target=countdown, args=(10,), daemon=True) t.start() 后台线程无法等待,不过,这些线程会在主线程终止时自动销毁。 除了如上所示的两个操作,并没有太多可以对线程做的事情。你无法结束一个线程,无法给它发送信号,无法调整它的调度,也无法执行其他高级操作。如果需要这些特性,你需要自己添加。比如说,如果你需要终止线程,那么这个线程必须通过编程在某个特定点轮询来退出。你可以像下边这样把线程放入一个类中: class CountdownTask: def __init__(self): self._running = True def terminate(self): self._running = False def run(self, n): while self._running and n > 0: print('T-minus', n) n -= 1 time.sleep(5) c = CountdownTask() t = Thread(target=c.run, args=(10,)) t.start() c.terminate() # Signal termination t.join() # Wait for actual termination (if needed) 如果线程执行一些像I/O这样的阻塞操作,那么通过轮询来终止线程将使得线程之间的协调变得非常棘手。比如,如果一个线程一直阻塞在一个I/O操作上,它就永远无法返回,也就无法检查自己是否已经被结束了。要正确处理这些问题,你需要利用超时循环来小心操作线程。 例子如下: class IOTask: def terminate(self): self._running = False def run(self, sock): # sock is a socket sock.settimeout(5) # Set timeout period while self._running: # Perform a blocking I/O operation w/ timeout try: data = sock.recv(8192) break except socket.timeout: continue # Continued processing ... # Terminated return

哦哦喔 2020-04-17 17:19:15 0 浏览量 回答数 0

回答

哈,没细看,我把我这边server和client端的代码贴给你,你参考一下,看是不是有什么步骤遗漏了。。。 _Isetup_server(_shostname,_Iport,_SERVER_FUNCprf,_SERVER_FUNCpwf,_Inum){_SOCKETIDsockfd,new_fd;_Ire=0;_Ii;structsockaddr_inclient_addr;socklen_taddr_size=sizeof(structsockaddr_in);_i32chk;structsockaddr_inservaddr;structtimevaltv;fd_setfdsr;_i32lastminute,maxsock,flag;signal(SIGPIPE,sig_send_err);ms_serverid=0;sockfd=socket(AF_INET,SOCK_STREAM,ms_potol);_error(sockfd==-1,_setup_server_ERR,"createsocketerror:%s(errno:%d)\n",strerror(errno),errno);chk=setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&ms_socket_reuse_opt,sizeof(ms_socket_reuse_opt));_error(chk==-1,_setup_server_close_ERR,"setsockoptSO_REUSEADDRerror:%s(errno:%d)\n",strerror(errno),errno);memset(&servaddr,0,sizeof(servaddr));servaddr.sin_family=AF_INET;servaddr.sin_port=htons(port);chk=inet_pton(AF_INET,hostname,&servaddr.sin_addr);_error(chk<=0,_setup_server_close_ERR,"inet_ptonerrorfor%s",hostname);chk=bind(sockfd,(structsockaddr*)&servaddr,sizeof(servaddr));_error(chk==-1,_setup_server_close_ERR,"bindsocketerror:%s(errno:%d)",strerror(errno),errno);chk=listen(sockfd,ms_backlog);_error(chk==-1,_setup_server_close_ERR,"listensocketerror:%s(errno:%d)",strerror(errno),errno);lastminute=get_current_min();maxsock=sockfd;_log("maxsock%d",maxsock);printf("======waitingforclient'srequest======\n");ms_conn_num=0; 以上server,以下client _Isetup_client(_shostname,_Iport,_CLIENT_FUNCprf,_CLIENT_FUNCpwf){_SOCKETIDsockfd;_i32chk;_Ire=0;_It;structsockaddr_inservaddr;signal(SIGPIPE,sig_send_err);_error((prf==0)&&(pwf==0),_setup_client_ERR,"norece,nosenddowhat?");sockfd=socket(AF_INET,SOCK_STREAM,0);_error(sockfd<0,_setup_client_ERR,"createsocketerror:%s(errno:%d)\n",strerror(errno),errno);memset(&servaddr,0,sizeof(servaddr));servaddr.sin_family=AF_INET;servaddr.sin_port=htons(port);chk=inet_pton(AF_INET,hostname,&servaddr.sin_addr);_error(chk<=0,_setup_client_close_ERR,"inet_ptonerrorfor%s\n",hostname);chk=connect(sockfd,(structsockaddr*)&servaddr,sizeof(servaddr));_error(chk<0,_setup_client_close_ERR,"connecterror:%s(errno:%d)\n",strerror(errno),errno); 其他的类型定义你不用去理解,都是我自己的类型定义,你跟踪两个变量就ok了。_shostname和_Iport;“_s"是我自己定义字符串类型等于char*,_I可以等于unsignedint类型,上面两端代码是我测试过的。。你对应一下。 另外我可不大神。哈。 看来没时间 ,不过,还要谢谢 你的server代码有明显的错误啊。 第35行修改为==-1不是==0: if(bind(service_sockfd,(structsockaddr*)&service_addr,sizeof(service_addr))==-1) 把第26行去掉: bzero(&(service_addr),sizeof(service_addr)); 我测试了一下server,在1234端口已经监听成功了,后面的下载你再继续测试看看~ 回复 @徐永强:回答问题对楼主有帮助,也没评上个最佳答案啥的,没积分,就不能赢开源内裤,没内裤只好裸奔了~T.T1、也许多数人都不喜欢读别人代码。2、这层“答的基本合格”,呵呵。耐心阅读楼主的代码、编译、测试,值得学习提倡。3、楼主新代码可以边写边测试观察,像监听不上的问题,netstat就可以发现。为什么要去掉bzero(&(service_addr),sizeof(service_addr)); 第26行为什么去掉,你先要想一下这第26行为什么加呢? bzero函数的用处:Thebzero()functionsetsthefirstnbytesofthebyteareastartingatstozero(bytescontaining’\0’). 你前面对server_addr的各种赋值,一个bzero把它全搞没了,后面还怎么玩? 所以这一行要么去掉,要么放在service_addr定义之后属性赋值之前,要么直接修改为: bzero(&(service_addr.sin_zero),8); sin_zero是保留的空字节,设不设置对你这个程序没有影响~ 回复 @tb_engineer:哥们,既然认为回答的不错,好歹给个积分啥的,让俺也有机会赢个开源内裤穿穿~~T.T好的,明白了,万分感谢

爱吃鱼的程序员 2020-06-15 10:48:16 0 浏览量 回答数 0

回答

首先 我想说的是 这个东西 写起来 真的很优雅 很舒服 看着也清晰 感觉代码就应该这么写 其次 我想说 如果只是用于数据的展示 (不提交数据 或者只是将数据取出来 然后处理)这个用起来 是非常棒的 但是要是处理业务的话 最好还是用原生的Java代码 说一下和原生的servlet的区别 我们之前用的东西(servlet) 都是将结果 处理处理好 然后 返回 一层一层的返回 就是说 在mapping到合适的方法后 这个方法执行完后 浏览器所期望的数据 已经生成了 然后 就是一层 一层的往外走 最后直接给浏览器 因而 如果请求很多的话 因为这个方法 要把 结果处理出来 才返回 所以 请量很大的时候 吞吐量就上不去了 (这里暂时想不到合适的例子) webflux就不一样了 我之前 有疑惑但是明白这一点后 也就意识到为什么要这么做了 先说下结论 webflux 在mapping的方法里面 并不是返回结果 而是返回 数据与函数的组合(Mono Flux) 所以在mapping的方法中 不会花费很多时间 所以同等情况下 要比servlet的吞吐量大 @GetMapping(path = "/applications", produces = MediaType.TEXT_EVENT_STREAM_VALUE) public Flux<ServerSentEvent<Application>> applicationsStream() { return Flux.from(eventPublisher) .flatMap(event -> registry.getInstance(event.getInstance())) .map(this::getApplicationForInstance) .flatMap(group -> toApplication(group.getT1(), group.getT2())) .map(application -> ServerSentEvent.builder(application).build()) .mergeWith(ping()); } 如上图代码 返回的是一个flux对象 里面包含了数据 与处理的方法 但是并不执行 只有在真正需要的时候 才去执行里面的方法 并放回最终的结果(和spark里的rdd处理 如出一辙) 一直说的异步io 关键点就在这里 至于后面的数据提取 最终返回 就要看里面的源码了 这里说下我之前的疑惑 Mono和Flux的都实现了 Publisher 里面有个subscribe方法 public abstract class Flux<T> implements Publisher<T> { .....} public abstract class Mono<T> implements Publisher<T> { ....} public interface Publisher<T> { /** * Request {@link Publisher} to start streaming data. * <p> * This is a "factory method" and can be called multiple times, each time starting a new {@link Subscription}. * <p> * Each {@link Subscription} will work for only a single {@link Subscriber}. * <p> * A {@link Subscriber} should only subscribe once to a single {@link Publisher}. * <p> * If the {@link Publisher} rejects the subscription attempt or otherwise fails it will * signal the error via {@link Subscriber#onError}. * * @param s the {@link Subscriber} that will consume signals from this {@link Publisher} */ public void subscribe(Subscriber<? super T> s); } 数据的处理函数 貌似都是写到这个方法里面 最后在进行调用 当时我不明白的事 这个不是直接返回结果吗 干嘛还在这里面 写个类似订阅的方法 知道了上面的后 就说清楚了 结果不是立刻返回 而是在最后使用结果的时候 在调用具体的方法(这里其实是函数)然后获取结果 感觉这个和scala有点接近了

wangccsy 2019-12-02 01:47:32 0 浏览量 回答数 0

问题

SPFA在devc上运行出错,C++? 400 报错

爱吃鱼的程序员 2020-06-03 16:36:30 1 浏览量 回答数 1

问题

C语言结构体指针问题?报错

爱吃鱼的程序员 2020-06-12 10:26:39 7 浏览量 回答数 2

回答

1:使用mtk 工具解析aee_exp,找到发生NE 进程信息如: pid: 5832, tid: 5840, name: AudioOut_15 >>> /system/bin/audioserver <<< 2:确定版本信息,需要aee_exp 与outtargetproductA31symbols 编译生成的是同一次的 3:使用gat 工具 Backtrace decode 解析异常堆栈 backtrace 文件选择aee_exp 中 __exp_main.txt symbols 选择上边sysmbols目录 会生成__exp_main.txt .decode.txt 解析的文件与函数及行信息。 4:根据__exp_main.txt .decode.txt判断调用关系是否正确,有可能 symbols 与aee_exp 代码不是同一次编译的。 5:使用Trace32 simulator 加载 NE 的lib trace32 下载 http://www.lauterbach.com/frames.html?manual.html 6:打开coredumpM、N相同M版本 ENG load 默认开启 M版本Userdebug load:adb shell aee -d coreon adb shell aee -d directon adb reboot 使用user 版本,烧录userdebug 版本boot img root ,这个时候如果出现unknow coreon 或 unknow directon ,需要将/system/build.prop 下ro.build.type=user 改为userdebug 在reboot 手机,再运行adb shell aee -d coreon adb shell aee -d directon 等手机重启后再执行以下命令 adb shell setprop persist.libc.debug.malloc 15 adb shell setprop persist.libc.debug15.prog /system/bin/surfaceflinger adb shell setprop persist.debug15.config 0x4a003024 adb reboot 手机再次重启后,开始复现问题。 M版本 USER load:1)open alps/bionic/linker/debugger.cpp, and modify code in debuggerd_initLIBC_HIDDEN void debuggerd_init() {struct sigaction action;memset(&action, 0, sizeof(action));sigemptyset(&action.sa_mask);action.sa_sigaction = debuggerd_signal_handler;action.sa_flags = SA_RESTART | SA_SIGINFO; if 0 // Use the alternate signal stack if available so we can catch stack overflows.action.sa_flags |= SA_ONSTACK; sigaction(SIGABRT, &action, nullptr);sigaction(SIGBUS, &action, nullptr);sigaction(SIGFPE, &action, nullptr);sigaction(SIGILL, &action, nullptr);sigaction(SIGPIPE, &action, nullptr);sigaction(SIGSEGV, &action, nullptr); if defined(SIGSTKFLT) sigaction(SIGSTKFLT, &action, nullptr); endif sigaction(SIGTRAP, &action, nullptr); endif } 2)rebuild load3)need enable root permission firstadb shell setprop persist.aee.core.dump enableadb shell setprop persist.aee.core.direct enableadb reboot memory map (2293 entries):--->Fault address falls at 00000020 before any mapped regions

元芳啊 2019-12-02 00:55:41 0 浏览量 回答数 0

问题

Qt多线程的问题,子线程中的this指的是什么??报错

爱吃鱼的程序员 2020-06-14 22:08:56 0 浏览量 回答数 1

问题

你可能不知道的 Python 技巧有哪些?

游客bnlxddh3fwntw 2020-04-13 11:34:27 33 浏览量 回答数 1

回答

使用os.system("cmd")特点是执行的时候程序会打出cmd在linux上执行的信息。import osos.system("ls")使用Popen模块产生新的process现在大部分人都喜欢使用Popen。Popen方法不会打印出cmd在linux上执行的信息。的确,Popen非常强大,支持多种参数和模式。使用前需要from subprocess import Popen, PIPE。但是Popen函数有一个缺陷,就是它是一个阻塞的方法。如果运行cmd时产生的内容非常多,函数非常容易阻塞住。解决办法是不使用wait()方法,但是也不能获得执行的返回值了。Popen原型是:subprocess.Popen(args, bufsize=0, executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=False, shell=False, cwd=None, env=None, universal_newlines=False, startupinfo=None, creationflags=0) 参数bufsize:指定缓冲。参数executable用于指定可执行程序。一般情况下我们通过args参数来设置所要运行的程序。如果将参数shell设为 True,executable将指定程序使用的shell。在windows平台下,默认的shell由COMSPEC环境变量来指定。参数stdin, stdout, stderr分别表示程序的标准输入、输出、错误句柄。他们可以是PIPE,文件描述符或文件对象,也可以设置为None,表示从父进程继承。参数preexec_fn只在Unix平台下有效,用于指定一个可执行对象(callable object),它将在子进程运行之前被调用。参数Close_sfs:在windows平台下,如果close_fds被设置为True,则新创建的子进程将不会继承父进程的输入、输出、错误管 道。我们不能将close_fds设置为True同时重定向子进程的标准输入、输出与错误(stdin, stdout, stderr)。如果参数shell设为true,程序将通过shell来执行。参数cwd用于设置子进程的当前目录。参数env是字典类型,用于指定子进程的环境变量。如果env = None,子进程的环境变量将从父进程中继承。参数Universal_newlines:不同操作系统下,文本的换行符是不一样的。如:windows下用’/r/n’表示换,而Linux下用 ‘/n’。如果将此参数设置为True,Python统一把这些换行符当作’/n’来处理。参数startupinfo与createionflags只在windows下用效,它们将被传递给底层的CreateProcess()函数,用 于设置子进程的一些属性,如:主窗口的外观,进程的优先级等等。subprocess.PIPE在创建Popen对象时,subprocess.PIPE可以初始化stdin, stdout或stderr参数,表示与子进程通信的标准流。subprocess.STDOUT创建Popen对象时,用于初始化stderr参数,表示将错误通过标准输出流输出。Popen的方法:Popen.poll() 用于检查子进程是否已经结束。设置并返回returncode属性。Popen.wait() 等待子进程结束。设置并返回returncode属性。Popen.communicate(input=None)与子进程进行交互。向stdin发送数据,或从stdout和stderr中读取数据。可选参数input指定发送到子进程的参数。 Communicate()返回一个元组:(stdoutdata, stderrdata)。注意:如果希望通过进程的stdin向其发送数据,在创建Popen对象的时候,参数stdin必须被设置为PIPE。同样,如 果希望从stdout和stderr获取数据,必须将stdout和stderr设置为PIPE。Popen.send_signal(signal) 向子进程发送信号。Popen.terminate()停止(stop)子进程。在windows平台下,该方法将调用Windows API TerminateProcess()来结束子进程。Popen.kill()杀死子进程。Popen.stdin 如果在创建Popen对象是,参数stdin被设置为PIPE,Popen.stdin将返回一个文件对象用于策子进程发送指令。否则返回None。Popen.stdout 如果在创建Popen对象是,参数stdout被设置为PIPE,Popen.stdout将返回一个文件对象用于策子进程发送指令。否则返回 None。Popen.stderr 如果在创建Popen对象是,参数stdout被设置为PIPE,Popen.stdout将返回一个文件对象用于策子进程发送指令。否则返回 None。Popen.pid 获取子进程的进程ID。Popen.returncode 获取进程的返回值。如果进程还没有结束,返回None。例如:p = Popen("cp -rf a/* b/", shell=True, stdout=PIPE, stderr=PIPE) p.wait() if p.returncode != 0: print "Error." return -1使用commands.getstatusoutput方法这个方法也不会打印出cmd在linux上执行的信息。这个方法唯一的优点是,它不是一个阻塞的方法。即没有Popen函数阻塞的问题。使用前需要import commands。例如:status, output = commands.getstatusoutput("ls") 还有只获得output和status的方法:commands.getoutput("ls") commands.getstatus("ls")

xuning715 2019-12-02 01:10:25 0 浏览量 回答数 0

问题

为什么Scipy有不同的函数'signal.convolve2d'和'signal.correlate2d'?

一码平川MACHEL 2019-12-01 19:31:54 1184 浏览量 回答数 1

回答

线程的一个关键特性是每个线程都是独立运行且状态不可预测。如果程序中的其他线程需要通过判断某个线程的状态来确定自己下一步的操作,这时线程同步问题就会变得非常棘手。为了解决这些问题,我们需要使用 threading 库中的 Event 对象。 Event 对象包含一个可由线程设置的信号标志,它允许线程等待某些事件的发生。在初始情况下,event 对象中的信号标志被设置为假。如果有线程等待一个 event 对象,而这个 event 对象的标志为假,那么这个线程将会被一直阻塞直至该标志为真。一个线程如果将一个 event 对象的信号标志设置为真,它将唤醒所有等待这个 event 对象的线程。如果一个线程等待一个已经被设置为真的 event 对象,那么它将忽略这个事件,继续执行。 下边的代码展示了如何使用 Event 来协调线程的启动: from threading import Thread, Event import time # Code to execute in an independent thread def countdown(n, started_evt): print('countdown starting') started_evt.set() while n > 0: print('T-minus', n) n -= 1 time.sleep(5) # Create the event object that will be used to signal startup started_evt = Event() # Launch the thread and pass the startup event print('Launching countdown') t = Thread(target=countdown, args=(10,started_evt)) t.start() # Wait for the thread to start started_evt.wait() print('countdown is running') 当你执行这段代码,“countdown is running” 总是显示在 “countdown starting” 之后显示。这是由于使用 event 来协调线程,使得主线程要等到 countdown() 函数输出启动信息后,才能继续执行。

哦哦喔 2020-04-17 17:19:35 0 浏览量 回答数 0

问题

使用 Snort 和 PHP 构建一个小型网络防御系统 400 请求报错 

kun坤 2020-05-28 16:31:41 3 浏览量 回答数 1
阿里云大学 云服务器ECS com域名 网站域名whois查询 开发者平台 小程序定制 小程序开发 国内短信套餐包 开发者技术与产品 云数据库 图像识别 开发者问答 阿里云建站 阿里云备案 云市场 万网 阿里云帮助文档 免费套餐 开发者工具 SQL审核 小程序开发制作 视频内容分析 企业网站制作 视频集锦 代理记账服务 2020阿里巴巴研发效能峰会 企业建站模板 云效成长地图 高端建站 人工智能 阿里云云栖号 云栖号案例 云栖号直播