免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: cascle
打印 上一主题 下一主题

怎么样才能传多个参数给signal函数的回调函数? [复制链接]

论坛徽章:
0
21 [报告]
发表于 2010-05-08 13:16 |只看该作者
#include <signal.h>
void (*signal(int sig, void (*func)(int)))(int);

signal() 函数第一个参数是要安装的信号量,第二个参数是对第一个参数指定的信号的处理。
信号处理函数只能传入一个int型。所以使用全局变量是一个方法。

论坛徽章:
11
未羊
日期:2013-12-16 12:45:4615-16赛季CBA联赛之青岛
日期:2016-04-11 19:17:4715-16赛季CBA联赛之广夏
日期:2016-04-06 16:34:012015亚冠之卡尔希纳萨夫
日期:2015-11-10 10:04:522015亚冠之大阪钢巴
日期:2015-07-30 18:29:402015亚冠之城南
日期:2015-06-15 17:56:392015亚冠之卡尔希纳萨夫
日期:2015-05-15 15:19:272015亚冠之山东鲁能
日期:2015-05-14 12:38:13金牛座
日期:2014-12-04 15:34:06子鼠
日期:2014-10-16 13:40:4715-16赛季CBA联赛之八一
日期:2016-07-22 09:41:40
22 [报告]
发表于 2010-05-08 14:04 |只看该作者
本帖最后由 zylthinking 于 2010-05-08 14:12 编辑
回复  zylthinking

没看见callback是自己调用的, 而不是传递给什么信号处理啊?
难道setvbuf你也只会 ...
OwnWaterloo 发表于 2010-05-08 10:21


脾气倒是不小; 还抓不住重点。。。。。。。, 有什么重点还请指教。

我倒是看清callback是你主动调的了, 不过有些奇怪的是你既然可以主动调用回调, 说明这个函数接口很大可能就是你定的, 为什么你要定这么一个回调签名呢? 具体到这个case, 很显然, 你的代码了充当了实现OS信号机制的角色, 哦, 你给我动态创建看看什么参数, OS 还能知道用户程序动态参数, 牛大了你, 哦, 不是动态参数, 是静态的, 那干嘛不用全局变量呢, 全局变量很丑陋是吗, 全局变量不是面向对象是吗, 你的代码不客气的说比全局变量丑陋的多。 要面向对象? 哦, 你的示例代码为什么是纯粹的C风格呢?


就算这个接口不是你定义的吧, 另外一个场景, 你被要求在执行你的代码到这个场景必须调用某个回调函数, 既然是回调函数, 我是不是可以理解成传进来的函数地址是可变的, 函数的实现是可变的? 由的你自己造一块内存, 在上面折腾出某一段代码说这就是用户传给你的回调函数吗, 何况你自己折腾出来的代码逻辑看上去就是一个跳转, 传进来的回调自己本身的逻辑就不管了?

你的二进制栈代码是什么意思说实话我根本没看懂, 不过我猜也就是人为造栈, 造返回地址, 然后jump到你真正的handler去, 对, 你可以 VirtualProtect, VirtualWrite, 再加上 mmap 一大堆, 即便我给你动态传某个回调说不定你也可是跳到你的handler去, 甚至还可以在调用 handler 之前将我传给你的回调先执行一遍也有可能, 等等, 对不起, 这样似乎先后执行 callback(int); handler(int, int); 调用序列差不多, 对不起你辛勤的劳动。

还有你的机器代码, 你的是 x86 呢还是 arm 呢; 好歹要加上 #ifdef #else ................ #endif 吧?


要说你的demo成功在那里, 其实在于成功的演示了函数调用栈, 成功演示了如何将数据段换成代码段; 不懂的人可以从中学到这些比较重要的基础, 所谓知所以然; 而写出这样的代码的你, 说不定也YY 自己的本事可真不小(有些恶意了啊, 不好意思); 要用在实际编码上, 我先妄下断言, 事倍功半。

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
23 [报告]
发表于 2010-05-08 17:37 |只看该作者
本帖最后由 OwnWaterloo 于 2010-05-08 17:41 编辑

回复 22# zylthinking

傻了吧唧的。 看不懂就虚心请教, 别唧唧歪歪。

写这么明白都看不懂:
callback( arg ) 等效于 handler(context, arg );
这就是楼上所说的partial application机制

明眼人看到这里就懂了, 这种机制可以用来做什么
你要这么笨, 我可以勉为其难为你写得更复杂点:

  1. void handler(void* context, int sig);

  2. void f(void) {
  3.     callback = dynamic_allocate(sizeof layout);
  4.     context  = dynamic_allocate(sizeof context);
  5.     bind(callback, handler, context);
  6.     signal(SIG_XXX, callback);
  7. }

  8. ...

  9. void g(void) {
  10.     raise(SIG_XXX); // handler(context, SIG_XXX);
  11. }
复制代码
是不是非要这么写你才看得懂?
啥智商? 一点点举一反三都不会?


定个屁。lz是在问signal, 要signal的签名可以改, 还问个毛。
我不自己主动调用, 难道你要我把signal的实现代码给写出来?

你就是那种讨论问题老是out of topic的

lz列出需求, 你要更改, 说通常没有这个需求。

lx列出实现, 你又要唧唧歪歪。

demo代码, 还加#ifdef, 你x吗? demo代码就是为了短小让人一眼看出重点。加上了不是更让你这种x看不懂吗?

加了#ifdef又怎样? 像你这种x, 肯定又会说: VirtualAlloc分配有粒度, 要实现内存分配。

实现了又怎样? 像你这种x, 肯定又会继续跑题, 内存分配不是多线程安全的, 要多线程安全。

多线程安全了又怎样, 像你这种x, 肯定还会继续跑题: 现在流行无锁数据结构, 要实现成无锁线程安全的。

你这种x永远找得到话题, 永远抓不住重点。
要跑题谁不会? 看不懂瞎评价瞎嚷嚷谁不会? 低级!

论坛徽章:
11
未羊
日期:2013-12-16 12:45:4615-16赛季CBA联赛之青岛
日期:2016-04-11 19:17:4715-16赛季CBA联赛之广夏
日期:2016-04-06 16:34:012015亚冠之卡尔希纳萨夫
日期:2015-11-10 10:04:522015亚冠之大阪钢巴
日期:2015-07-30 18:29:402015亚冠之城南
日期:2015-06-15 17:56:392015亚冠之卡尔希纳萨夫
日期:2015-05-15 15:19:272015亚冠之山东鲁能
日期:2015-05-14 12:38:13金牛座
日期:2014-12-04 15:34:06子鼠
日期:2014-10-16 13:40:4715-16赛季CBA联赛之八一
日期:2016-07-22 09:41:40
24 [报告]
发表于 2010-05-08 19:48 |只看该作者
本帖最后由 zylthinking 于 2010-05-08 20:28 编辑
回复  zylthinking

傻了吧唧的。 看不懂就虚心请教, 别唧唧歪歪。

写这么明白都看不懂:
callback ...
OwnWaterloo 发表于 2010-05-08 17:37


你他妈要是牛就告诉我你所谓的牛大了的机制和下面代码有什么优点

int bind[max_signal] = {0};
void g(){
bindS[SIGXXX] = (int)"fuck your mother";
raise(SIGXXX);
}

void xxhandler(int x){
    char* pch = (char *) bind[SIGXXX];
    ...................
}

int main(){

signal(SIGXXX, xxhandler);
g();
}

你他妈的看样子也只会喷粪
另外狗日的看清楚, 我说没说通常没有这种需求的话, 狗日的眼睛长到头顶上去, 看不清了是不是
狗日的说demo的代码不用#ifdef, 这倒是实情, 你妈的你拿出一个办法把你的牛逼代码拿到实际应用中也不用 #ifdef 的办法来, 有种, 要脸的话就不要用和 #ifdef 只是字面上差异的那些办法
另外狗日的低下你钉在头顶上的狗眼看清楚我一开始质疑的就是你孙子实现到底有什么现实意义, 第二个帖子是好言好语说出我之所以认为没意义的理由, 之所以口气也不是很友好就是你这个**第一篇回复的帖子口气也不咋地-----这篇帖子还是那个意思, 老子就是认为没什么意义, 要有意义, 你说出意义在什么地方, 别告诉我就是老子上面几行代码就能实现的效果----------从头到尾, 老子始终就是一个意思, 你狗日的张嘴闭嘴跑题, 跑你妈个头啊。
你狗日的出言不逊, 谁还不会骂人不成。 草你妈的

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
25 [报告]
发表于 2010-05-08 22:00 |只看该作者
本帖最后由 OwnWaterloo 于 2010-05-08 22:03 编辑

回复 24# zylthinking

不懂莫装

的会把完整souce code放到论坛上帖出来?
见过newbie是怎么帖代码的吗?

爷实际项目中用不用#ifdef 关你求事。 你又out of topic了。

使用全局变量的绑定, 除了newbie, 不会?
我要是你, 根本就不好意思开口说出来。 初级


爷现在就告诉你意义。
如果使用全局的变量,或者全局变量的变体比如tss —— 且不说全局变量的其他问题 —— 那么:
一个函数实现体任意时刻只能对应一个闭包
而通过partial application产生的可调用体是相互独立的

  1. void* f_arg;        // f_arg
  2. void f(int sig) {   // 与f 一一对应
  3.     access(f_arg);
  4. }

  5. f_bind( void* arg ) { // f_bind函数和f, f_arg一一对应
  6.     f_arg = arg;
  7.     return f;
  8. }

  9. callback1  = f_bind(context1);
  10. callback1(sig); //f(context1, sig);
  11. callback2  = f_bind(context2);
  12. callback2(sig); //f(context2, sig);
  13. assert( callback1 == callback2 );
  14. callback1(sig); //f(context2, sig); // 这根本不是2个闭包, 而是1个
复制代码
而partial application产生的是相互独立的闭包:

  1. closure1 = papply(f, context1);
  2. closure1(sig);  //f(context1, sig);
  3. closure2 = papply(f, context2);
  4. closure2(sig);  //f(context2, sig);
  5. closure1(sig);  //f(context1, sig); // 这才是2个闭包, 相互之间是独立的
复制代码
有种你实现一个

  1. void signal_add(int sig
  2.                ,void (*handler)(void* context, int sig)
  3.                ,void* context);
复制代码
看看?

知道两者的区别了吗?

论坛徽章:
11
未羊
日期:2013-12-16 12:45:4615-16赛季CBA联赛之青岛
日期:2016-04-11 19:17:4715-16赛季CBA联赛之广夏
日期:2016-04-06 16:34:012015亚冠之卡尔希纳萨夫
日期:2015-11-10 10:04:522015亚冠之大阪钢巴
日期:2015-07-30 18:29:402015亚冠之城南
日期:2015-06-15 17:56:392015亚冠之卡尔希纳萨夫
日期:2015-05-15 15:19:272015亚冠之山东鲁能
日期:2015-05-14 12:38:13金牛座
日期:2014-12-04 15:34:06子鼠
日期:2014-10-16 13:40:4715-16赛季CBA联赛之八一
日期:2016-07-22 09:41:40
26 [报告]
发表于 2010-05-08 23:51 |只看该作者
本帖最后由 zylthinking 于 2010-05-09 00:57 编辑
回复  zylthinking

个**, 不懂莫装逼。

你他妈的会把完整souce code放到论坛上帖出来?
见过new ...
OwnWaterloo 发表于 2010-05-08 22:00



好, 既然你说我不懂莫装逼, 那就接着来。 这次心平气和了点, 就不问候你了。

既然闭包了老半天, 似乎高深莫测, 我偏偏还是愚钝, 还是老问题问你, 你的实现比我上面贴出的代码优点在哪里?
不过我似乎发现是你听不懂我的啊, 还是我搞不明白你的高深之处啊,
closure2(sig);  //f(context2, sig);
closure1(sig);  //f(context1, sig); // 这才是2个闭包, 相互之间是独立的

哦, 了不起, 那我简单拿你的代码试上一试,  不好意思极了, 我还是随手乱写代码, 就是看上去不好看, 你爱看不看

handler1();
handler2();

void f(void) {

    callback1 = dynamic_allocate(sizeof layout);
    context1  = dynamic_allocate(sizeof context);
    bind(callback, handler1, context1);

    callback2 = dynamic_allocate(sizeof layout);
    context2  = dynamic_allocate(sizeof context);
    bind(callback, handler2, context2);

    signal(SIG_XXX, callback1);
    signal(SIG_XXX, callback2);
}

void g(void) {
    raise(SIG_XXX); // handler(context, SIG_XXX);
}

好了, 信号出来了, 你倒是说调了哪一个呢, 你那么不**, 相比能告诉我了?
要是你还是不明白, 那我也勉为其难, 多说上一些, 你至少不可能两个都调。

你是不是想实现这样的效果?

int bind[max_signal] = {0};

void g1(int SIGXXX){
bindS[SIGXXX] = (int)"fuck your mother1";
}

void g2(int SIGXXX){
bindS[SIGXXX] = (int)"fuck your mother2";
}

void xxhandler(int x){
    char* pch = (char *) bind[SIGXXX];
    ...................
}


int main(){

signal(SIGXXX, xxhandler);
g1(SIGXXX);
g2(SIGXXX);
raise(SIGXXX);
}

似乎我很低级的又弄出来了
==============================================================


void signal_add(int sig
               ,void (*handler)(void* context, int sig)
               ,void* context);
这个东西, 我实现不了, 你也实现不了, 原因在于信号处理函数不排队, 和你机制不机制没有你所谓的"球"关系, 你构建所谓的闭包再完美, 真正的绑定是signal函数, 白亏你阳春白雪, 还是一样和我大街上讨饭的一起争食, 你觉得你高贵, 很高级? 笑死人了, 我就是很低级, 我就是笑死了。

考虑到signal handler 只能 replace 不能add, 如果只考虑replace, 还有什么难的吗
你他妈那么牛的人, 怎么在这个判断上阴沟里翻船了呢

要说不是signal语义, 而是另外一种语义:  依次调用add进去的所有函数指针,
首先我要说这是你拿你的实现外显的特点出题, 你能malloc出一系列可执行代码出来, 其他实现只能在源文件里静态写好, 所以你觉得只有你的实现能写的出来?

struct A{
    func_type func_ptr;
    void* context;
    void closure(int sig){
        this->func_ptr(sig, context);
    };
   
    A* next;
}

A* root[MAX_SIGNAL] = {0};

void signal_add(int sig
               ,void (*handler)(void* context, int sig)
               ,void* context)
{
        A* r = root[sig];
        下面 list 操作, 懒得写了
        ...............................
}

call_handler(sig){
     找相应 list, 依次调closure
}


觉得还是很低级? 可就是能运行, 你能怎么地? 觉得侮辱你的学问? 你还别说, 爷的连 #ifdef 都不用, 爷还不觉的#ifdef是跑题, 爷觉得这是你没法回避的一个大麻烦。

你要一定说你的好, 你回帖一定要多多说明是哪里好, 开门语似的给人扣帽子, 还是少些的好。
你牛别人就人傻么, 你有多牛啊, 张嘴闭嘴不懂莫装逼, 其实你说错了, 应该是不管你懂不懂都不要装逼, 装逼被雷劈的。

论坛徽章:
0
27 [报告]
发表于 2010-05-09 00:56 |只看该作者
弱弱的问一下,你们写的代码都是什么平台的,我怎么以前没有见过callback和bind在一起的?

另外楼主的问题,我的想法是:
1:定义一个结构体,包含所有需要的参数
2:动态分配这个结构体,并填充实际的参数
3:将此结构体的地址强制转换为int类型,作为signal handler的参数
4:在signal handler函数中将int参数强转为定义的结构体类型,使用其中的参数,释放此结构体占用的内存

论坛徽章:
11
未羊
日期:2013-12-16 12:45:4615-16赛季CBA联赛之青岛
日期:2016-04-11 19:17:4715-16赛季CBA联赛之广夏
日期:2016-04-06 16:34:012015亚冠之卡尔希纳萨夫
日期:2015-11-10 10:04:522015亚冠之大阪钢巴
日期:2015-07-30 18:29:402015亚冠之城南
日期:2015-06-15 17:56:392015亚冠之卡尔希纳萨夫
日期:2015-05-15 15:19:272015亚冠之山东鲁能
日期:2015-05-14 12:38:13金牛座
日期:2014-12-04 15:34:06子鼠
日期:2014-10-16 13:40:4715-16赛季CBA联赛之八一
日期:2016-07-22 09:41:40
28 [报告]
发表于 2010-05-09 01:05 |只看该作者
弱弱的问一下,你们写的代码都是什么平台的,我怎么以前没有见过callback和bind在一起的?

另外楼主的问 ...
cymx2002 发表于 2010-05-09 00:56



你不用管它, 那是他自己写的函数, 就是将一块内存和他分配出的另一块以后用于可执行代码绑定, 也就是制造出调用栈中的参数的。
至于平台, 都是瞎写, 没考虑什么平台

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
29 [报告]
发表于 2010-05-09 01:14 |只看该作者
本帖最后由 OwnWaterloo 于 2010-05-09 01:22 编辑

回复 26# zylthinking

你依然没有理解partial application到底是怎么回事。

就说你这个效果

closure1 = papply(f, context1);
closure1(sig);  //f(context1, sig);
closure2 = papply(f, context2);
closure2(sig);  //f(context2, sig);
closure1(sig);  //f(context1, sig);

你觉的只有你的机器码能实现?

struct A{
    func_type func_ptr;
    void* context;
    void closure(int sig){
        this->func_ptr(sig, context);
    };
}

papply(f, context1){
    a = (A*) malloc(A);
    a->func = f;
    a->context = context1;
    return a;
}

A* pa1 = papply(f, context1);
A* pa2 = papply(f, context2);

pa1->closure(sig);
pa2->closure(sig);
zylthinking 发表于 2010-05-08 23:51[img][/img]


搞笑了。
pa1->closure(sig);  << 这是什么东西?
partial application得到的是一个函数, free function。 而不是什么member function。

你可以closure(sig)来调用吗?  this怎么传递
如果不行, 你怎么将它传递给signal
你这代码根本没有解决问题缺少一个context
你只是将context放到一个class中, 然后将问题转换为如何传递instance
脱了裤子放屁而已
如此初级代码也敢拿出来show?

所以我说你直到现在都没能理解我写的代码究竟是实现了什么机制。


void signal_add(int sig
               ,void (*handler)(void* context, int sig)
               ,void* context);
这个东西, 我实现不了, 你也实现不了, 原因在于信号处理函数不排队, 和你机制不机制没有你所谓的"球"关系, 你构建所谓的闭包再完美, 真正的绑定是signal函数, 白亏你阳春白雪, 还是一样和我大街上讨饭的一起争食, 你觉得你高贵, 很高级? 笑死人了, 我就是很低级, 我就是笑死了。
zylthinking 发表于 2010-05-08 23:51[img][/img]


你以为我会像你一样? 对完全没把握的事也敢

看好了:

  1. void
  2. continuation
  3. (
  4.       void (*prev)(int   sig),
  5.       void (*next)(void* ctx, int sig),
  6.       void*  ctx,
  7.       int    sig
  8. )
  9. {
  10.       prev(sig);
  11.       next(ctx, sig);
  12. }

  13. void
  14. signal_add
  15. (
  16.       int    sig,
  17.       void (*handler)(void*, int),
  18.       void*  ctx
  19. )
  20. {
  21.       old = signal(sig, 0);
  22.       now = bind(continuation, old, handler, ctx);
  23.       signal(sig, now);
  24. }
复制代码
本来如果signal的签名设计不存在缺陷的话, 根本无须搞这么多动作。
可是它的确有缺陷, 而且这种不带context的回调签名在legacy设计中多得是
以C标准库为例: qsort, bsearch, atexit都是。
为什么posix要实现这么多xxx_r函数? 你以为是好玩吗?

你用你的阳春白雪式实现上面的东西看看?

closure会对编程技法产生怎样的影响, 我看你没法体会的。
一辈子用你的全局变量,
一辈子头痛医头脚痛医脚去吧。



你要一定说你的好, 你回帖一定要多多说明是哪里好, 开门语似的给人扣帽子, 还是少些的好。
你牛别人就傻么, 你有多牛啊, 笑死我这个低级的了
zylthinking 发表于 2010-05-08 23:51[img][/img]


我从一开始就给出一个方案可以解决楼主的问题。
而你居然可以在
完全不理解这方案, 也不自己给出方案的情况下:
先在19楼说出一个传递栈变量的笑话;
然后在22楼继续扯到代码风格;
还可以YY我如何如何, 还可以下断言如何如何。

你脸皮可真是不薄!

我没说我多牛, 我也没说这方案多好多好。
可我至少不会
不懂装懂, 乱扣帽子, 张嘴打哈哈

论坛徽章:
0
30 [报告]
发表于 2010-05-09 01:23 |只看该作者
明天再研究一下你们的代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP