linux内核中的信号机制--信号处理

发布者:心愿成真最新更新时间:2016-03-02 来源: eefocus关键字:linux内核  信号机制  信号处理 手机看文章 扫描二维码
随时随地手机看文章
Kernel version:2.6.14

CPU architecture:ARM920T

Author:ce123(http://blog.csdn.net/ce123)

当进程被调度时,会调用do_notify_resume()来处理信号队列中的信号。信号处理主要就是调用sighand_struct结构中对应的信号处理函数。do_notify_resume()(arch/arm/kernel/signal.c)函数的定义如下:

 

 

[plain] view plain copy
 
 print?
  1. asmlinkage void  
  2. do_notify_resume(struct pt_regs *regs, unsigned int thread_flags, int syscall)  
  3. {  
  4.     if (thread_flags & _TIF_SIGPENDING)  
  5.         do_signal(¤t->blocked, regs, syscall);  
  6. }  
_TIF_SIGPENDING标志是在signal_wake_up()函数中设置的,检查该标志后,接下来就调用do_signal()函数,我们来看看do_signal()(arch/arm/kernel/signal.c)的具体定义:

 

[plain] view plain copy
 
 print?
  1. /*  
  2.  * Note that 'init' is a special process: it doesn't get signals it doesn't  
  3.  * want to handle. Thus you cannot kill init even with a SIGKILL even by  
  4.  * mistake.  
  5.  *  
  6.  * Note that we go through the signals twice: once to check the signals that  
  7.  * the kernel can handle, and then we build all the user-level signal handling  
  8.  * stack-frames in one go after that.  
  9.  */  
  10. static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)  
  11. {  
  12.     struct k_sigaction ka;  
  13.     siginfo_t info;  
  14.     int signr;  
  15.   
  16.     /*  
  17.      * We want the common case to go fast, which  
  18.      * is why we may in certain cases get here from  
  19.      * kernel mode. Just return without doing anything  
  20.      * if so.  
  21.      */  
  22.     if (!user_mode(regs))//regs保存的是进入内核态之前的寄存器现场,必须为用户模式,否则直接返回  
  23.         return 0;  
  24.   
  25.     if (try_to_freeze())  
  26.         goto no_signal;  
  27.   
  28.     if (current->ptrace & PT_SINGLESTEP)  
  29.         ptrace_cancel_bpt(current);//和调试相关,我们在后面的文章中会具体分析  
  30.   
  31.     signr = get_signal_to_deliver(&info, &ka, regs, NULL);//取出等待处理的信号  
  32.     if (signr > 0) {  
  33.         handle_signal(signr, &ka, &info, oldset, regs, syscall);//处理信号  
  34.         if (current->ptrace & PT_SINGLESTEP)  
  35.             ptrace_set_bpt(current);  
  36.         return 1;  
  37.     }  
  38.   
  39.  no_signal:  
  40.     /*  
  41.      * No signal to deliver to the process - restart the syscall.  
  42.      */  
  43.     if (syscall) {  
  44.         if (regs->ARM_r0 == -ERESTART_RESTARTBLOCK) {  
  45.             if (thumb_mode(regs)) {  
  46.                 regs->ARM_r7 = __NR_restart_syscall;  
  47.                 regs->ARM_pc -= 2;  
  48.             } else {  
  49.                 u32 __user *usp;  
  50.   
  51.                 regs->ARM_sp -= 12;  
  52.                 usp = (u32 __user *)regs->ARM_sp;  
  53.   
  54.                 put_user(regs->ARM_pc, &usp[0]);  
  55.                 /* swi __NR_restart_syscall */  
  56.                 put_user(0xef000000 | __NR_restart_syscall, &usp[1]);  
  57.                 /* ldr  pc, [sp], #12 */  
  58.                 put_user(0xe49df00c, &usp[2]);  
  59.   
  60.                 flush_icache_range((unsigned long)usp,  
  61.                            (unsigned long)(usp + 3));  
  62.   
  63.                 regs->ARM_pc = regs->ARM_sp + 4;  
  64.             }  
  65.         }  
  66.         if (regs->ARM_r0 == -ERESTARTNOHAND ||  
  67.             regs->ARM_r0 == -ERESTARTSYS ||  
  68.             regs->ARM_r0 == -ERESTARTNOINTR) {  
  69.             restart_syscall(regs);  
  70.         }  
  71.     }  
  72.     if (current->ptrace & PT_SINGLESTEP)  
  73.         ptrace_set_bpt(current);  
  74.     return 0;  
  75. }  

 

执行do_signal()函数时,进程一定处于内核空间,通常进程只有通过中断或者系统调用才能进入内核空间,regs保存着系统调用或者中断时的现场。user_mode()根据regs中的cpsr寄存器来判断是中断现场环境还是用户态环境。如果不是用户态环境,就不对信号进行任何处理,直接从do_signal()函数返回。

如果user_mode()函数发现regs的现场是内核态,那就意味着这不是一次系统调用的返回,也不是一次普通的中断返回,而是一次嵌套中断返回(或者在系统调用过程中发生了中断)。此时大概的执行路径应该是这样的:假设进场现在运行在用户态,此时发生一次中断,进场进入内核态(此时user_mode(regs)返回1,意味着中断现场是用户态。),此后在中断返回前,发生了一个更高优先级的中断,于是CPU开始执行高优先级的处理函数(此时user_mode(regs)返回0,意味着中断现场是在内核态)。当高优先级中断处理结束后,在它返回时,是不应该处理信号的,因为信号的优先级比中断的优先级低。在这种情况下,对信号的处理将会延迟到低优先级中断处理结束之后。相对于Windows内核来说,尽管linux内核中没有一组显式的操作函数来实现这一系列的优先级管理方案,但是linux内核和Windows内核都使用了同样的机制,优先级关系为:高优先级中断->低优先级中断->软中断(类似Windows内中的DPC)->信号(类似Windows内核中的APC)->进程运行。

如果user_mode(regs)返回1,接下来会执行(中间略去一下和本文关系不大的代码)get_signal_to_deliver(),这个函数从当前进程的信号队列(保存Private Signal Queue和Shared Signal Queue)取出等待处理的信号(调用dequeue_signal()函数),然后根据信号定位到对应的signal_struct结构,如果信号的处理函数sa_handler为SIG_IGN,就忽略该信号,继续取下一个信号;如果信号的处理函数sa_handler为SIG_DFL,意味着按照信号默认的处理方式对待就可以了(例如直接调用do_coredump()等)。

如果get_signal_to_deliver()函数返回值大于0,说明这个信号的处理函数是在用户态空间(通过signal()和sigaction()等函数设置的自定义信号处理函数。),将调用handle_signal()函数进行处理。handle_signal()函数的定义如下:

 

[plain] view plain copy
 
 print?
  1. /*  
  2.  * OK, we're invoking a handler  
  3.  */   
  4. static void  
  5. handle_signal(unsigned long sig, struct k_sigaction *ka,  
  6.           siginfo_t *info, sigset_t *oldset,  
  7.           struct pt_regs * regs, int syscall)  
  8. {  
  9.     struct thread_info *thread = current_thread_info();  
  10.     struct task_struct *tsk = current;  
  11.     int usig = sig;  
  12.     int ret;  
  13.   
  14.     /*  
  15.      * If we were from a system call, check for system call restarting...  
  16.      */  
  17.     if (syscall) {  
  18.         switch (regs->ARM_r0) {  
  19.         case -ERESTART_RESTARTBLOCK:  
  20.         case -ERESTARTNOHAND:  
  21.             regs->ARM_r0 = -EINTR;  
  22.             break;  
  23.         case -ERESTARTSYS:  
  24.             if (!(ka->sa.sa_flags & SA_RESTART)) {  
  25.                 regs->ARM_r0 = -EINTR;  
  26.                 break;  
  27.             }  
  28.             /* fallthrough */  
  29.         case -ERESTARTNOINTR:  
  30.             restart_syscall(regs);  
  31.         }  
  32.     }  
  33.   
  34.     /*  
  35.      * translate the signal  
  36.      */  
  37.     if (usig < 32 && thread->exec_domain && thread->exec_domain->signal_invmap)  
  38.         usig = thread->exec_domain->signal_invmap[usig];  
  39.   
  40.     /*  
  41.      * Set up the stack frame//设置栈帧  
  42.      */  
  43.     if (ka->sa.sa_flags & SA_SIGINFO)  
  44.         ret = setup_rt_frame(usig, ka, info, oldset, regs);  
  45.     else  
  46.         ret = setup_frame(usig, ka, oldset, regs);  
  47.   
  48.     /*  
  49.      * Check that the resulting registers are actually sane.  
  50.      */  
  51.     ret |= !valid_user_regs(regs);  
  52.   
  53.     /*  
  54.      * Block the signal if we were unsuccessful.  
  55.      */  
  56.     if (ret != 0) {  
  57.         spin_lock_irq(&tsk->sighand->siglock);  
  58.         sigorsets(&tsk->blocked, &tsk->blocked,  
  59.               &ka->sa.sa_mask);  
  60.         if (!(ka->sa.sa_flags & SA_NODEFER))  
  61.             sigaddset(&tsk->blocked, sig);  
  62.         recalc_sigpending();  
  63.         spin_unlock_irq(&tsk->sighand->siglock);  
  64.     }  
  65.   
  66.     if (ret == 0)  
  67.         return;  
  68.   
  69.     force_sigsegv(sig, tsk);  
  70. }  
在这样情况下,进程当前处于内核态,而信号处理函数却处于用户态,为此必须在进程的用户态构造一个临时的堆栈环境(因为进程的信号处理函数在进行函数调用以及使用局部变量时需要使用堆栈。),然后进入用户态执行信号处理函数,最后再返回内核态继续执行。在这个过程中,有以下几个问题需要解决:

 

1.临时的用户态堆栈在哪里呢?这个很好解决,因为可以直接使用进程现有的用户态堆栈,这里要保证的是:使用结束后这个堆栈必须和使用前是一模一样的。

2.临时堆栈解决后,需要确定的是通过什么方法来保证返回到用户态后,进程执行的是信号的处理函数。我们知道在进入内核态时,内核态堆栈中保存了一个中断现场,也就是一个pt_regs结构,中断返回地址就保存在pt_regts中的pc中,因此我们这里只要把当前进程的pt_regs中pc设置为sa_handler,然后返回到用户态就开始从sa_handler处开始执行了。

 

[plain] view plain copy
 
 print?
  1. unsigned long handler = (unsigned long)ka->sa.sa_handler;  
  2. regs->ARM_pc = handler;  

 

3.当信号的用户态处理函数执行结束时,需要再次进入内核态,还原用户态堆栈,并且修改pt_regs中的pc,保证将来能够按照正常的方式返回用户态。我们知道进程要主动进入内核态只有通过系统调用,出发异常等方法,为此内核专门提供了一个系统调用sys_sigreturn()(还有一个sys_rt_sigreturn()),但是如何调用sys_sigreturn()呢?强制安装信号处理函数最后必须调用一个sigreturn()不是一个好办法,因为不了解内核的程序员会对这个限制感到不解,为此程序员常常忘记在它们的信号处理函数的末尾调用sigreturn(),如果真是这样,arm-linux-gcc也检测不出这个错误。为此,内核修改regs的ARM_lr值,:

 

[plain] view plain copy
 
 print?
  1. regs->ARM_lr = retcode;  

当用户态信号处理函数运行结束时,会从lr取出返回地址,因此内核在构建临时regs时,会把上面这段代码的入口地址保存在lr,这样当信号处理完成后,就会顺利的通过系统调用sys_sigreturn()进入内核。

4.当通过构造的sys_sigreturn()返回到内核态之后,内核需要顺利的返回到用户态执行原来的代码(信号处理前应该返回的用户空间状态),但是此时进入内核空间的pt_regs上下文是通过sys_sigreturn()构造的,而最初的内核堆栈中的pt_regs上下文在第一次返回用户空间执行信号处理函数时,就已经被“销毁”了(内核态堆栈的pt_regs上下文在中断返回后就不复存在了)。而现在必须通过最初的pt_regs上下文返回用户态,为此,在构建临时堆栈环境时,内核会把最初的pt_regs上下文备份到临时堆栈中(位于用户态堆栈),当通过系统调用sys_sigreturn()再次进入内核时,内核从用户态空间还原出原始的pt_regs。最后正常返回。

通过上面的讨论,我们知道在这个迂回的处理过程中,关键在于用户态的临时堆栈环境的建立,这是一个sigframe结构:

 

[plain] view plain copy
 
 print?
  1. /*  
  2.  * Do a signal return; undo the signal stack.  These are aligned to 64-bit.  
  3.  */  
  4. struct sigframe {  
  5.     struct sigcontext sc;//保存一组寄存器上下文  
  6.     unsigned long extramask[_NSIG_WORDS-1];  
  7.     unsigned long retcode;//保存返回地址  
  8.     struct aux_sigframe aux __attribute__((aligned(8)));  
  9. };  
  10.   
  11. struct rt_sigframe {  
  12.     struct siginfo __user *pinfo;  
  13.     void __user *puc;  
  14.     struct siginfo info;  
  15.     struct ucontext uc;  
  16.     unsigned long retcode;  
  17.     struct aux_sigframe aux __attribute__((aligned(8)));  
  18. };  
其中的sigcontext的作用类似于pt_regs用于保存相关寄存器上下文,原始的pt_regs的相关信息就备份在这里。而整个sigframe结构是通过get_sigframe()函数在进程用户态空间分配的,get_sigframe()定义如下:

 

 

[plain] view plain copy
 
 print?
  1. static inline void __user *  
  2. get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, int framesize)  
  3. {  
  4.     unsigned long sp = regs->ARM_sp;  
  5.     void __user *frame;  
  6.   
  7.     /*  
  8.      * This is the X/Open sanctioned signal stack switching.  
  9.      */  
  10.     if ((ka->sa.sa_flags & SA_ONSTACK) && !sas_ss_flags(sp))  
  11.         sp = current->sas_ss_sp + current->sas_ss_size;  
  12.   
  13.     /*  
  14.      * ATPCS B01 mandates 8-byte alignment  
  15.      */  
  16.     frame = (void __user *)((sp - framesize) & ~7);  
  17.   
  18.     /*  
  19.      * Check that we can actually write to the signal frame.  
  20.      */  
  21.     if (!access_ok(VERIFY_WRITE, frame, framesize))  
  22.         frame = NULL;  
  23.   
  24.     return frame;  
  25. }  
get_sigframe()通过用户态空间堆栈的sp-sizeof(struct sigframe)在用户态堆栈的顶部分配了一篇存储空间,将来使用完成后,再通过sp+sizeof(struct sigframe)还原。

 

通过上面的讨论,我们再回到do_signal()中来,如果有用户态的信号处理函数,do_signal()会调用handle_signal(),handle_signal()将调用setup_frame()或者setup_rt_frame()来完成实际的工作,这里我们以setup_frame()为例进行进一步讨论。

 

[plain] view plain copy
 
 print?
  1. static int  
  2. setup_frame(int usig, struct k_sigaction *ka, sigset_t *set, struct pt_regs *regs)  
  3. {  
  4.     //在用户态堆栈上分配一个sigframe结构  
  5.     struct sigframe __user *frame = get_sigframe(ka, regs, sizeof(*frame));  
  6.     int err = 0;  
  7.   
  8.     if (!frame)  
  9.         return 1;  
  10.   
  11.     //把相关信息从内核态备份到用户态堆栈的sigframe结构中  
  12.     err |= setup_sigcontext(&frame->sc, &frame->aux, regs, set->sig[0]);  
  13.   
  14.     if (_NSIG_WORDS > 1) {  
  15.         err |= __copy_to_user(frame->extramask, &set->sig[1],  
  16.                       sizeof(frame->extramask));  
  17.     }  
  18.   
  19.     if (err == 0)  
  20.         err = setup_return(regs, ka, &frame->retcode, frame, usig);  
  21.   
  22.     return err;  
  23. }  
setup_return()设置返回地址,其定义如下:

 

[plain] view plain copy
 
 print?
  1. static int  
  2. setup_return(struct pt_regs *regs, struct k_sigaction *ka,  
  3.          unsigned long __user *rc, void __user *frame, int usig)  
  4. {  
  5.     unsigned long handler = (unsigned long)ka->sa.sa_handler;  
  6.     unsigned long retcode;  
  7.     int thumb = 0;  
  8.     unsigned long cpsr = regs->ARM_cpsr & ~PSR_f;  
  9.   
  10.     /*  
  11.      * Maybe we need to deliver a 32-bit signal to a 26-bit task.  
  12.      */  
  13.     if (ka->sa.sa_flags & SA_THIRTYTWO)  
  14.         cpsr = (cpsr & ~MODE_MASK) | USR_MODE;  
  15.   
  16. #ifdef CONFIG_ARM_THUMB  
  17.     if (elf_hwcap & HWCAP_THUMB) {  
  18.         /*  
  19.          * The LSB of the handler determines if we're going to  
  20.          * be using THUMB or ARM mode for this signal handler.  
  21.          */  
  22.         thumb = handler & 1;  
  23.   
  24.         if (thumb)  
  25.             cpsr |= PSR_T_BIT;  
  26.         else  
  27.             cpsr &= ~PSR_T_BIT;  
  28.     }  
  29. #endif  
  30.   //这里的retcode就是保存手工构造的sigreturn()代码  
  31.     if (ka->sa.sa_flags & SA_RESTORER) {  
  32.         retcode = (unsigned long)ka->sa.sa_restorer;  
  33.     } else {  
  34.         unsigned int idx = thumb;  
  35.   
  36.         if (ka->sa.sa_flags & SA_SIGINFO)  
  37.             idx += 2;  
  38.   
  39.         if (__put_user(sigreturn_codes[idx], rc))  
  40.             return 1;  
  41.   
  42.         if (cpsr & MODE32_BIT) {  
  43.             /*  
  44.              * 32-bit code can use the new high-page  
  45.              * signal return code support.  
  46.              */  
  47.             retcode = KERN_SIGRETURN_CODE + (idx << 2) + thumb;  
  48.         } else {  
  49.             /*  
  50.              * Ensure that the instruction cache sees  
  51.              * the return code written onto the stack.  
  52.              */  
  53.             flush_icache_range((unsigned long)rc,  
  54.                        (unsigned long)(rc + 1));  
  55.   
  56.             retcode = ((unsigned long)rc) + thumb;  
  57.         }  
  58.     }  
  59.   
  60.     regs->ARM_r0 = usig;  
  61.     regs->ARM_sp = (unsigned long)frame;//堆栈  
  62.     regs->ARM_lr = retcode;//返回地址,当用户态信号处理函数结束时,就会把这个地址作为返回地址  
  63.     regs->ARM_pc = handler;//信号处理函数  
  64.     regs->ARM_cpsr = cpsr;  
  65.   
  66.     return 0;  
  67. }  

当setup_frame()返回后,一切准备就绪,因此可以从内核态返回了,这样就顺利过渡到用户态的信号处理函数。当这个函数处理结束后,会通过retcode再次进入内核态,现在我们看看retcode是如何处理的,下面的代码选自glibc(2.3.2):

 

[plain] view plain copy
 
 print?
  1.  #include   
  2.   
  3. /* If no SA_RESTORER function was specified by the application we use  
  4.    one of these.  This avoids the need for the kernel to synthesise a return  
  5.    instruction on the stack, which would involve expensive cache flushes. */  
  6.   
  7. ENTRY(__default_sa_restorer)  
  8.     swi SYS_ify(sigreturn)  
  9.   
  10. #ifdef __NR_rt_sigreturn  
  11.   
  12. ENTRY(__default_rt_sa_restorer)  
  13.     swi SYS_ify(rt_sigreturn)  
  14.   
  15. #define SYS_ify(syscall_name)   (__NR_##syscall_name)  

 

下面具体看看sys_sigreturn()的定义:

[plain] view plain copy
 
 print?
  1. asmlinkage int sys_sigreturn(struct pt_regs *regs)  
  2. {  
  3.     struct sigframe __user *frame;  
  4.     sigset_t set;  
  5.   
  6.     /* Always make any pending restarted system calls return -EINTR */  
  7.     current_thread_info()->restart_block.fn = do_no_restart_syscall;  
  8.   
  9.     /*  
  10.      * Since we stacked the signal on a 64-bit boundary,  
  11.      * then 'sp' should be word aligned here.  If it's  
  12.      * not, then the user is trying to mess with us.  
  13.      */  
  14.     if (regs->ARM_sp & 7)  
  15.         goto badframe;  
  16.   
  17.     frame = (struct sigframe __user *)regs->ARM_sp;  
  18.   
  19.     if (!access_ok(VERIFY_READ, frame, sizeof (*frame)))  
  20.         goto badframe;  
  21.     if (__get_user(set.sig[0], &frame->sc.oldmask)  
  22.         || (_NSIG_WORDS > 1  
  23.             && __copy_from_user(&set.sig[1], &frame->extramask,  
  24.                     sizeof(frame->extramask))))  
  25.         goto badframe;  
  26.   
  27.     sigdelsetmask(&set, ~_BLOCKABLE);  
  28.     spin_lock_irq(¤t->sighand->siglock);  
  29.     current->blocked = set;  
  30.     recalc_sigpending();  
  31.     spin_unlock_irq(¤tt->sighand->siglock);  
  32.   
  33.     if (restore_sigcontext(regs, &frame->sc, &frame->aux))  
  34.         goto badframe;  
  35.   
  36.     /* Send SIGTRAP if we're single-stepping */  
  37.     if (current->ptrace & PT_SINGLESTEP) {  
  38.         ptrace_cancel_bpt(current);  
  39.         send_sig(SIGTRAP, current, 1);  
  40.     }  
  41.   
  42.     return regs->ARM_r0;  
  43.   
  44. badframe:  
  45.     force_sig(SIGSEGV, current);  
  46.     return 0;  
  47. }  
这个函数主要调用restore_sigcontext()根据用户态态堆栈上的sigframe备份还原pt_regs。

 

[plain] view plain copy
 
 print?
  1. static int  
  2. restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,  
  3.            struct aux_sigframe __user *aux)  
  4. {  
  5.     int err = 0;  
  6.   
  7.     __get_user_error(regs->ARM_r0, &sc->arm_r0, err);  
  8.     __get_user_error(regs->ARM_r1, &sc->arm_r1, err);  
  9.     __get_user_error(regs->ARM_r2, &sc->arm_r2, err);  
  10.     __get_user_error(regs->ARM_r3, &sc->arm_r3, err);  
  11.     __get_user_error(regs->ARM_r4, &sc->arm_r4, err);  
  12.     __get_user_error(regs->ARM_r5, &sc->arm_r5, err);  
  13.     __get_user_error(regs->ARM_r6, &sc->arm_r6, err);  
  14.     __get_user_error(regs->ARM_r7, &sc->arm_r7, err);  
  15.     __get_user_error(regs->ARM_r8, &sc->arm_r8, err);  
  16.     __get_user_error(regs->ARM_r9, &sc->arm_r9, err);  
  17.     __get_user_error(regs->ARM_r10, &sc->arm_r10, err);  
  18.     __get_user_error(regs->ARM_fp, &sc->arm_fp, err);  
  19.     __get_user_error(regs->ARM_ip, &sc->arm_ip, err);  
  20.     __get_user_error(regs->ARM_sp, &sc->arm_sp, err);  
  21.     __get_user_error(regs->ARM_lr, &sc->arm_lr, err);  
  22.     __get_user_error(regs->ARM_pc, &sc->arm_pc, err);  
  23.     __get_user_error(regs->ARM_cpsr, &sc->arm_cpsr, err);  
  24.   
  25.     err |= !valid_user_regs(regs);  
  26.   
  27. #ifdef CONFIG_IWMMXT  
  28.     if (err == 0 && test_thread_flag(TIF_USING_IWMMXT))  
  29.         err |= restore_iwmmxt_context(&aux->iwmmxt);  
  30. #endif  
  31. #ifdef CONFIG_VFP  
  32. //  if (err == 0)  
  33. //      err |= vfp_restore_state(&aux->vfp);  
  34. #endif  
  35.   
  36.     return err;  
  37. }  
restore_sigcontext()很简单,当它返回后,通过sys_sigreturn()在内核态堆栈建立的pt_regs已经变为调用信号处理函数之前的pt_regs。这样,sys_sigreturn()返回用户态时,就顺利地过渡到处理之前的状态了。
关键字:linux内核  信号机制  信号处理 引用地址:linux内核中的信号机制--信号处理

上一篇:linux内核中的信号机制--从用户层到内核层
下一篇:linux内核中的信号机制--信号发送

推荐阅读最新更新时间:2024-03-16 14:45

数字信号处理入门指南
什么是DSP? 数字信号处理器(DSP)采集已被数字化的现实世界的声音、音频、视频、温度、压力或位置等信号,并从数学的角度对其进行处理。DSP被设计用于快速执行“加”、“减”、“乘”、“除”等算术运算。 信号需要进行处理,这样其包含的信息才能被显示、分析或转换成另外一种可以利用的信号类型。在现实世界中,模拟产品探测声音、光、温度或压力等信号,并对其进行处理。模数转换器等转换器采集现实世界信号,并将其转换为1、0等数字格式。然后,DSP采集并处理数字化信息,再将数字化信息反馈至现实世界中应用。反馈可由两种方式中的任一种实现,或是数字化的,或是通过数模转换器将数字信息转换为模拟格式。所有处理都以非常高的速度进行。 为了说明这
[嵌入式]
数字<font color='red'>信号处理</font>入门指南
基于CAN总线的单片机与数字信号处理器通信系统设计
0 引 言 众所周知,虽然目前8位单片机正逐渐被速度高,性能强的16位或32位微处理器所取代,但8位单片机仍以其低廉的价格、丰富的外围芯片以及众多的多功能产品而在低端应用市场占据主流地位。数字信号处理器(Digital Signal Processor,DSP)作为一种具有高速数字信号处理能力的新型单片机,在通信、自动控制、航天航空、军事、医疗等领域广泛应用。在比较复杂的测控系统中,如微机电动机保护装置,要求在毫秒级的短时间内对电动机实现实时保护和测量,所以对装置硬件系统的实时数据处理能力要求较高,而传统的基于单 CPU微处理器的方案己经难以胜任。因此,这里采用数字信号处理器与单片机构成的双CPU结构。由数字信号处理器完成多
[单片机]
基于CAN总线的单片机与数字<font color='red'>信号处理</font>器通信系统设计
虚拟仪器的关键是什么?
虚拟仪器的关键是什么? 虚拟仪器的关键是软件,由于虚拟仪器的信号处理功能和仪器控制功能都是用软件实现的,所以虚拟仪器在硬件平台确定以后,主要的工作是软件的编程。对用户和系统集成商来说,最终形成的虚拟仪器性能如何,主要取决于软件编程的质量。换句话说,软件就是仪器。
[测试测量]
使用RapidIO技术搭建可重构信号处理平台
  摘 要: 军事领域常选择ADI公司的TS201芯片用于信号处理平台,但由于其采用基于电路交换的LINK口进行连接,难以实现军方对电子系统设计提出的可重构性的需求。FPGA可以用来实现接口转换功能,如果利用FPGA将基于电路交换的LINK口转换成基于包交换的其他形式的接口,就能在不改变硬件连接的基础上,实现DSP系统的重构。本文介绍了一种基于串行RapidIO技术的可重构的信号处理平台,并对其中核心的FPGA的逻辑设计进行了讨论。   在雷达、声纳、电子对抗等军用电子设备中,数字信号处理机作为实现信号处理算法的平台,起着至关重要的作用。在传统的信号处理平台中,军事领域多选用ADI公司的TigerShark系列的DSP芯片作为信
[嵌入式]
基于tiny4412的Linux内核移植 -- 设备树的展开
平台简介 开发板:tiny4412ADK + S700 + 4GB Flash 要移植的内核版本:Linux-4.4.0 (支持device tree) u-boot版本:友善之臂自带的 U-Boot 2010.12 (为支持uImage启动,做了少许改动) busybox版本:busybox 1.25 交叉编译工具链: arm-none-linux-gnueabi-gcc (gcc version 4.8.3 20140320 (prerelease) (Sourcery CodeBench Lite 2014.05-29)) 摘要 在Linux引入设备树之后,将原来写在代码中的大量的硬件信息全部移到了
[单片机]
基于tiny4412的<font color='red'>Linux内核</font>移植 -- 设备树的展开
ccd信号处理电路
图片: =800) window.open('/article/UploadPic/2008-5/20085129028892.jpg');" border=0 src="http://www.elecfans.com/article/UploadPic/2008-5/20085129028892.jpg" onload="if(this.width>'800')this.width='800';if(this.height>'800')this.height='800';"> 红外CCD 信号处理电路的设计 摘 要:由于红外CCD 的输出为高背景、宽动态范围的信号,所以在该信号的处理电路中,去除直流高背景和自动增益对
[模拟电子]
基于双DSP的电力系统谐波分析仪的设计
本文介绍了一种基于双TMS320F 28335的电力系统谐波分析仪的设计方案,该分析仪可同时实现多通道信号(电压和电流)的同步采样,并对其进行谐波分析。借助强大的双TMS320F28335平台,实现了对信号的实时分析与显示,具有实时性好,运算速度快,精度高,灵活性好,系统扩展能力强等优点。 系统介绍 1 系统方案 由于本系统实时性要求较高且工作过程中有大量的数据传输和人机对话事件发生,而单个DSP资源有限,如果采用单个DSP处理数据,系统将不能及时处理采样数据并且可能会造成部分数据丢失从而影响系统整体性能。为弥补这一缺点,本设计提出了采用DSP+ DRAM+DSP的双处理器协同工作模式,一片DSP全权负责采集、
[嵌入式]
非陀螺寻北仪信号处理电路的设计与实现
高精度寻北仪可以分为传统的陀螺仪寻北仪和非陀螺寻北仪两类。利用陀螺仪寻北的方法受陀螺仪本身的精度和成本的限制,很难做到高精度和低成本并存。而利用高精度的加速度计研制非陀螺寻北仪则可突破这一局限,并可实现高精度、自动化、快速化寻北,从而成为寻北仪研究的一个新的技术方向。许多参考文献对该寻北原理和信号处理的方法进行了大量的仿真研究,但对电路的具体实现进行研究的较少,本文是进行该寻北仪电路构成的设计。 1 非陀螺寻北原理 非陀螺寻北的原理是将一只加速度计安装在恒速转台上,以转台边缘的某个切点为参考点(相对运动),其切向速度与地球自转角速度的北向分量形成复合运动产生哥氏加速度。通过转台动态调制,地球自转角速度的北向分量与该点上切向
[模拟电子]
非陀螺寻北仪<font color='red'>信号处理</font>电路的设计与实现
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved