在工作中遇到了一个问题,在
Linux2.4.*的系统中调用pthread_getschedparam函数时,第一个参数指定为0系统不宕,
而在Linux2.6的内核中调用该函数,第一个参数指定为0,则系统宕,原因是收到了SIGSEVG信号,也就是说程序访问的非法的地址。查了一晚上,应该是找到原因了。
首先看pthread_getschedparam函数的定义。
file COPYING.LIB;
* if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#include "pthre#include "sched.h"
int
pthread_getschedparam (pthread_t thread, int *po_kill (thread, 0);
if (0 != result)
{
return result;
}olicy and param args.
turn the priority value set by
* the most recent pthread_setschedparam() or pthread_create()
* for the target thread. It must not return the actual thread
* priority as altered by any system priority adjustments etc.
*/
param->sched_priority = ((ptw32_thread_t *)thread.p)->sched_priority;
return 0;
}
函数首先调用了pthread_kill函数,在查一下pthread_kill的定义。
<font face="Courier New">/** Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc. </font> |
<font face="Courier New">02</font> | This file is part of the GNU C Library. |
<font face="Courier New">03</font> | Contributed by Ulrich Drepper <[email protected]>, 2002. |
<font face="Courier New">04</font> | <font face="Courier New"> </font> |
<font face="Courier New">05</font> | The GNU C Library is free software; you can redistribute it and/or |
<font face="Courier New">06</font> | modify it under the terms of the GNU Lesser General Public |
<font face="Courier New">07</font> | License as published by the Free Software Foundation; either |
<font face="Courier New">08</font> | version 2.1 of the License, or (at your option) any later version. |
<font face="Courier New">09</font> | <font face="Courier New"> </font> |
<font face="Courier New">10</font> | The GNU C Library is distributed in the hope that it will be useful, |
<font face="Courier New">11</font> | but WITHOUT ANY WARRANTY; without even the implied warranty of |
<font face="Courier New">12</font> | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
<font face="Courier New">13</font> | Lesser General Public License for more details. |
<font face="Courier New">14</font> | <font face="Courier New"> </font> |
<font face="Courier New">15</font> | You should have received a copy of the GNU Lesser General Public |
<font face="Courier New">16</font> | License along with the GNU C Library; if not, write to the Free |
<font face="Courier New">17</font> | Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
<font face="Courier New">18</font> | 02111-1307 USA. */ |
<font face="Courier New">19</font> | <font face="Courier New"> </font> |
<font face="Courier New">20</font> | <font face="Courier New">#include <errno.h> </font> |
<font face="Courier New">21</font> | <font face="Courier New">#include <signal.h> </font> |
<font face="Courier New">22</font> | <font face="Courier New">#include <pthreadP.h> </font> |
<font face="Courier New">23</font> | <font face="Courier New">#include <tls.h> </font> |
<font face="Courier New">24</font> | <font face="Courier New">#include <sysdep.h> </font> |
<font face="Courier New">25</font> | <font face="Courier New">#include <kernel-features.h> </font> |
<font face="Courier New">26</font> | <font face="Courier New"> </font> |
<font face="Courier New">27</font> | <font face="Courier New"> </font> |
<font face="Courier New">28</font> | <font face="Courier New">int</font> |
<font face="Courier New">29</font> | <font face="Courier New">__pthread_kill (threadid, signo) </font> |
<font face="Courier New">30</font> | pthread_t threadid; |
<font face="Courier New">31</font> | int <font face="Courier New">signo; </font> |
<font face="Courier New">32</font> | <font face="Courier New">{ </font> |
<font face="Courier New">33</font> | struct pthread *pd = ( struct <font face="Courier New">pthread *) threadid; </font> |
<font face="Courier New">34</font> | <font face="Courier New"> </font> |
<font face="Courier New">35</font> | /** Make sure the descriptor is valid. */ |
<font face="Courier New">36</font> | if <font face="Courier New">(DEBUGGING_P && INVALID_TD_P (pd)) </font> |
<font face="Courier New">37</font> | /** Not a valid thread handle. */ |
<font face="Courier New">38</font> | return <font face="Courier New">ESRCH; </font> |
<font face="Courier New">39</font> | <font face="Courier New"> </font> |
<font face="Courier New">40</font> | /** Force load of pd->tid into local variable or register. Otherwise |
<font face="Courier New">41</font> | if a thread exits between ESRCH test and tgkill, we might return |
<font face="Courier New">42</font> | EINVAL, because pd->tid would be cleared by the kernel. */ |
<font face="Courier New">43</font> | pid_t tid = atomic_forced_read (pd->tid); |
<font face="Courier New">44</font> | if <font face="Courier New">(__builtin_expect (tid <= 0, 0)) </font> |
<font face="Courier New">45</font> | /** Not a valid thread handle. */ |
<font face="Courier New">46</font> | return <font face="Courier New">ESRCH; </font> |
<font face="Courier New">47</font> | <font face="Courier New"> </font> |
<font face="Courier New">48</font> | /** Disallow sending the signal we use for cancellation, timers, for |
<font face="Courier New">49</font> | for the setxid implementation. */ |
<font face="Courier New">50</font> | if <font face="Courier New">(signo == SIGCANCEL || signo == SIGTIMER || signo == SIGSETXID) </font> |
<font face="Courier New">51</font> | return <font face="Courier New">EINVAL; </font> |
<font face="Courier New">52</font> | <font face="Courier New"> </font> |
<font face="Courier New">53</font> | /** We have a special syscall to do the work. */ |
<font face="Courier New">54</font> | INTERNAL_SYSCALL_DECL (err); |
<font face="Courier New">55</font> | <font face="Courier New"> </font> |
<font face="Courier New">56</font> | /** One comment: The PID field in the TCB can temporarily be changed |
<font face="Courier New">57</font> | (in fork). But this must not affect this code here. Since this |
<font face="Courier New">58</font> | function would have to be called while the thread is executing |
<font face="Courier New">59</font> | fork, it would have to happen in a signal handler. But this is |
<font face="Courier New">60</font> | no allowed, pthread_kill is not guaranteed to be async-safe. */ |
<font face="Courier New">61</font> | int <font face="Courier New">val; </font> |
<font face="Courier New">62</font> | <font face="Courier New">#if __ASSUME_TGKILL </font> |
<font face="Courier New">63</font> | val = INTERNAL_SYSCALL (tgkill, err, 3, THREAD_GETMEM (THREAD_SELF, pid), |
<font face="Courier New">64</font> | tid, signo); |
<font face="Courier New">65</font> | <font face="Courier New">#else </font> |
<font face="Courier New">66</font> | <font face="Courier New"># ifdef __NR_tgkill </font> |
<font face="Courier New">67</font> | val = INTERNAL_SYSCALL (tgkill, err, 3, THREAD_GETMEM (THREAD_SELF, pid), |
<font face="Courier New">68</font> | tid, signo); |
<font face="Courier New">69</font> | if <font face="Courier New">(INTERNAL_SYSCALL_ERROR_P (val, err) </font> |
<font face="Courier New">70</font> | && INTERNAL_SYSCALL_ERRNO (val, err) == ENOSYS) |
<font face="Courier New">71</font> | <font face="Courier New"># endif </font> |
<font face="Courier New">72</font> | val = INTERNAL_SYSCALL (tkill, err, 2, tid, signo); |
<font face="Courier New">73</font> | <font face="Courier New">#endif </font> |
<font face="Courier New">74</font> | <font face="Courier New"> </font> |
<font face="Courier New">75</font> | return <font face="Courier New">(INTERNAL_SYSCALL_ERROR_P (val, err) </font> |
<font face="Courier New">76</font> | ? INTERNAL_SYSCALL_ERRNO (val, err) : 0); |
<font face="Courier New">77</font> | <font face="Courier New">} </font> |
<font face="Courier New">78</font> | <font face="Courier New">strong_alias (__pthread_kill, pthread_kill)</font> |
从中可以看到,在pthread_kill中,
if <font face="Courier New">(DEBUGGING_P && INVALID_TD_P (pd)) </font>
<font face="Courier New">37</font> | /** Not a valid thread handle. */ |
<font face="Courier New">38</font> | return <font face="Courier New">ESRCH; </font> |
首先进行了判断,但是很有可能DEBUGGING_P宏没定义,所以程序就跳了过去,
然后再
<font face="Courier New">43</font> | pid_t tid = atomic_forced_read (pd->tid); |
处访问了NULL指针,所以程序宕了。