Chinaunix首页 | 论坛 | 博客
  • 博客访问: 918580
  • 博文数量: 453
  • 博客积分: 7865
  • 博客等级: 少将
  • 技术积分: 5673
  • 用 户 组: 普通用户
  • 注册时间: 2011-06-29 16:21
个人简介

时光荏苒..

文章分类
文章存档

2015年(46)

2014年(22)

2013年(68)

2012年(218)

2011年(99)

分类: LINUX

2012-02-01 20:49:48

 
linux下c程序调用reboot函数实现直接重启

  当然你也可以直接调用system("reboot"),但是这里完全基于库函数来实现,不依赖于/sbin/reboot这个外部程序
这里reboot()的其他命令,比如RB_POWER_OFF,并不能保证关闭计算机电源.

#include
#include
int main()
{
    sync(); // 同步磁盘数据,将缓存数据回写到硬盘,以防数据丢失[luther.gliethttp]
    return reboot(RB_AUTOBOOT);
}

luther@gliethttp:~$ vim /usr/include/sys/reboot.h
/* Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
   This file is part of the GNU C Library.

   The GNU C Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.

   The GNU C Library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with the GNU C Library; if not, write to the Free
   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   02111-1307 USA.  */

/* This file should define RB_* macros to be used as flag
   bits in the argument to the `reboot' system call.  */

#ifndef _SYS_REBOOT_H
#define _SYS_REBOOT_H    1

#include

/* Perform a hard reset now.  */
#define RB_AUTOBOOT    0x01234567

/* Halt the system.  */
#define RB_HALT_SYSTEM    0xcdef0123

/* Enable reboot using Ctrl-Alt-Delete keystroke.  */
#define RB_ENABLE_CAD    0x89abcdef

/* Disable reboot using Ctrl-Alt-Delete keystroke.  */
#define RB_DISABLE_CAD    0

/* Stop system and switch power off if possible.  */
#define RB_POWER_OFF    0x4321fedc

__BEGIN_DECLS

/* Reboot or halt the system.  */
extern int reboot (int __howto) __THROW;

__END_DECLS

#endif    /* _SYS_REBOOT_H */

luther@gliethttp:~$ man 2 reboot

REBOOT(2)                  Linux Programmer’s Manual                 REBOOT(2)



NAME
       reboot - reboot or enable/disable Ctrl-Alt-Del

SYNOPSIS
       /* For libc4 and libc5 the library call and the system call
          are identical, and since kernel version 2.1.30 there are
          symbolic names LINUX_REBOOT_* for the constants and a
          fourth argument to the call: */

       #include
       #include

       int reboot(int magic, int magic2, int cmd, void *arg);

       /* Under glibc some of the constants involved have gotten
          symbolic names RB_*, and the library call is a 1-argument
          wrapper around the 3-argument system call: */

       #include
       #include

       int reboot(int cmd);

DESCRIPTION
       The  reboot()  call  reboots the system, or enables/disables the reboot
       keystroke (abbreviated CAD, since the default  is  Ctrl-Alt-Delete;  it
       can be changed using loadkeys(1)).

       This   system   call  will  fail  (with  EINVAL)  unless  magic  equals
       LINUX_REBOOT_MAGIC1   (that   is,   0xfee1dead)   and   magic2   equals
       LINUX_REBOOT_MAGIC2  (that  is, 672274793).  However, since 2.1.17 also
       LINUX_REBOOT_MAGIC2A  (that  is,  85072278)  and  since   2.1.97   also
       LINUX_REBOOT_MAGIC2B   (that  is,  369367448)  and  since  2.5.71  also
       LINUX_REBOOT_MAGIC2C (that is, 537993216) are permitted  as  value  for
       magic2.   (The  hexadecimal  values of these constants are meaningful.)
       The cmd argument can have the following values:

       LINUX_REBOOT_CMD_RESTART
              (RB_AUTOBOOT, 0x1234567).  The message "Restarting  system."  is
              printed, and a default restart is performed immediately.  If not
              preceded by a sync(2), data will be lost.

       LINUX_REBOOT_CMD_HALT
              (RB_HALT_SYSTEM, 0xcdef0123; since 1.1.76).  The message "System
              halted." is printed, and the system is halted.  Control is given
              to the ROM monitor, if there is  one.   If  not  preceded  by  a
              sync(2), data will be lost.

       LINUX_REBOOT_CMD_POWER_OFF
              (0x4321fedc;  since  2.1.30).   The  message  "Power  down."  is
              printed, the system is stopped, and all power  is  removed  from
              the  system,  if  possible.   If not preceded by a sync(2), data
              will be lost.

       LINUX_REBOOT_CMD_RESTART2
              (0xa1b2c3d4; since 2.1.30).  The message "Restarting system with
              command  '%s'"  is  printed,  and  a  restart (using the command
              string given in arg) is performed immediately.  If not  preceded
              by a sync(2), data will be lost.

       LINUX_REBOOT_CMD_CAD_ON
              (RB_ENABLE_CAD,  0x89abcdef).   CAD is enabled.  This means that
              the CAD keystroke will immediately cause the  action  associated
              with LINUX_REBOOT_CMD_RESTART.

       LINUX_REBOOT_CMD_CAD_OFF
              (RB_DISABLE_CAD,  0).  CAD is disabled.  This means that the CAD
              keystroke will cause a SIGINT signal to be sent to init (process
              1),  whereupon  this  process  may  decide  upon a proper action
              (maybe: kill all processes, sync, reboot).

       Only the superuser may call reboot().

       The precise effect of the above actions depends  on  the  architecture.
       For the i386 architecture, the additional argument does not do anything
       at present (2.1.122), but the type of reboot can be determined by  ker‐
       nel  command-line  arguments  ("reboot=...") to be either warm or cold,
       and either hard or through the BIOS.

RETURN VALUE
       For the values of cmd that stop or restart  the  system,  a  successful
       call  to  reboot()  does not return.  For the other cmd values, zero is
       returned on success.  In all cases, -1  is  returned  on  failure,  and
       errno is set appropriately.

ERRORS
       EFAULT Problem      with      getting      userspace     data     under
              LINUX_REBOOT_CMD_RESTART2.

       EINVAL Bad magic numbers or cmd.

       EPERM  The calling process has insufficient privilege to call reboot();
              the CAP_SYS_BOOT capability is required.

CONFORMING TO
       reboot() is Linux-specific, and should not be used in programs intended
       to be portable.

SEE ALSO
       sync(2),   bootparam(7),   capabilities(7),   ctrlaltdel(8),   halt(8),
       reboot(8)

COLOPHON
       This  page  is  part of release 3.01 of the Linux man-pages project.  A
       description of the project, and information about reporting  bugs,  can
       be found at



Linux                             2008-02-11                         REBOOT(2)
============================================================================================
 
-sh-3.2# ./reboot_my_exe
Restarting system.
kernel BUG at mm/slab.c:532!
Unable to handle kernel NULL pointer dereference at virtual address 00000000
pgd = 80004000
[00000000] *pgd=00000000
Internal error: Oops: 817 [#1] PREEMPT SMP
last sysfs file:
Modules linked in: [last unloaded: scsi_wait_scan]
CPU: 0    Not tainted  (2.6.32.24-arm-r1.0.0a3 #1)
PC is at __bug+0x24/0x2c
LR is at vprintk+0x360/0x510
pc : [<8002d610>]    lr : [<8004bc58>]    psr: 40000093
sp : c8e59eb8  ip : 00000001  fp : c8e59ec4
r10: 00000014  r9 : b2404000  r8 : 000bd60f
r7 : 00200200  r6 : 8039115c  r5 : 0000004a  r4 : c8e03f00
r3 : 00000000  r2 : c8e59de8  r1 : c8e58000  r0 : 00000023
Flags: nZcv  IRQs off  FIQs on  Mode SVC_32  ISA ARM  Segment kernel
Control: 10c53c7d  Table: dfbe404a  DAC: 00000017
Process events/0 (pid: 9, stack limit = 0xc8e582f8)
Stack: (0xc8e59eb8 to 0xc8e5a000)
9ea0:                                                       c8e59f0c c8e59ec8
9ec0: 800ae2f8 8002d5f8 00100100 c8e1c818 c8e59efc 00000060 000002e0 00000017
9ee0: 00000168 c8e1c800 c8e111a4 00000060 c8e1c818 c8e03f00 b2d3d660 80368080
9f00: c8e59f34 c8e59f10 800ae3a4 800ae184 00000000 c8e03f00 c8e11180 00000000
9f20: 80391ba8 80368080 c8e59f6c c8e59f38 800ae600 800ae304 00000000 800420cc
9f40: c8e59fc4 b2d3fde0 b2d3fde0 c8e58000 800ae534 b2d3fde8 b2d3d660 00000000
9f60: c8e59fbc c8e59f70 8005e218 800ae540 80000013 b2d3fdf0 80375d40 00000000
9f80: c8e30040 80062628 c8e59f88 c8e59f88 8003d0f4 c8e41ef0 00000002 8005e10c
9fa0: b2d3fde0 00000000 00000000 00000000 c8e59ff4 c8e59fc0 800623cc 8005e118
9fc0: 00000000 00000000 00000000 00000000 c8e59fd0 c8e59fd0 00000000 00000000
9fe0: 00000000 00000000 00000000 c8e59ff8 8004e8f0 80062350 00000000 00000000
Backtrace:
[<8002d5ec>] (__bug+0x0/0x2c) from [<800ae2f8>] (drain_array+0x0/0xd4)
[<800ae178>] (free_block+0x0/0x180) from [<800ae3a4>] (drain_array+0xac/0xd4)
[<800ae2f8>] (drain_array+0x0/0xd4) from [<800ae600>] (cache_reap+0xcc/0x148)
 r8:80368080 r7:80391ba8 r6:00000000 r5:c8e11180 r4:c8e03f00
r3:00000000
[<800ae534>] (cache_reap+0x0/0x148) from [<8005e218>] (worker_thread+0x10c/0x1ac)
[<8005e10c>] (worker_thread+0x0/0x1ac) from [<800623cc>] (kthread+0x88/0x90)
[<80062344>] (kthread+0x0/0x90) from [<8004e8f0>] (do_exit+0x0/0x6a0)
 r7:00000000 r6:00000000 r5:00000000 r4:00000000
Code: e3010acc e3480032 eb0a3a51 e3a03000 (e5833000)
---[ end trace 151d20490b8ed500 ]---
note: events/0[9] exited with preempt_count 1
 
 
分析,顾名思义,kernel 本身 的bug。//错误。这是kernel的报告信息,根源不在此
在下面的这句:  指针有问题!
Unable to handle kernel NULL pointer dereference at virtual address 00000000
pgd = 80004000
[00000000] *pgd=00000000
//野指针问题
 
查看源代码:
 
 530 static inline struct slab *page_get_slab(struct page *page)
    531 {
    532     BUG_ON(!PageSlab(page));
    533     return (struct slab *)page->lru.prev;
    534 }
    535
 
 
 
=============================================================================================
自己的reboot.c
    return reboot(RB_AUTOBOOT);
}
调用了reboot 参数是 RB_AUTOBOOT
 
所以查看Sysvinit中是否最终也是调用这个:
 
[zlg@localhost sysvinit-2.87dsf]$ grep -rn reboot(RB_AUTOBOOT) ./
-bash: syntax error near unexpected token `('
[zlg@localhost sysvinit-2.87dsf]$ grep -rn reboot\(RB_AUTOBOOT\) ./
我们来看有谁调用了参数RB_AUTOBOOT:
[zlg@localhost sysvinit-2.87dsf]$ grep -rn RB_AUTOBOOT ./         
./src/reboot.h:25:#define BMAGIC_REBOOT         RB_AUTOBOOT

原来给定义了个名字,那么我们查找新的名字BMAGIC_REBOOT:
 
[zlg@localhost sysvinit-2.87dsf]$ grep -rn BMAGIC_REBOOT ./
./src/shutdown.c:353:   init_reboot(BMAGIC_REBOOT);
./src/reboot.h:25:#define BMAGIC_REBOOT         RB_AUTOBOOT
./src/halt.c:268:               init_reboot(BMAGIC_REBOOT);
看到init_reboot调用了
 
[zlg@localhost sysvinit-2.87dsf]$ grep -rn init_reboot ./ 
./src/init.c.orig:2385: init_reboot(BMAGIC_SOFT);
./src/shutdown.c:348:           init_reboot(BMAGIC_HALT);
./src/shutdown.c:353:   init_reboot(BMAGIC_REBOOT);
./src/init.c:2386:      init_reboot(BMAGIC_SOFT);
./src/reboot.h:35:#define init_reboot(magic)    reboot(magic)
./src/halt.c:268:               init_reboot(BMAGIC_REBOOT);
./src/halt.c:274:               init_reboot(BMAGIC_HARD);
./src/halt.c:287:                       init_reboot(BMAGIC_POWEROFF);
./src/halt.c:291:               init_reboot(BMAGIC_HALT);
./src/halt.c:298:       init_reboot(BMAGIC_SOFT);
 
init_reboot即是我们猜测的reboot。即sysvinit中reboot和自己的reboot.c是同理的。
 
 
 
自己的reboot.c在板卡上不能执行的原因已经明确了是由于内核不能识别空指针。
sysvinit中init reboot失败 问题原因查明。
 
 
 
阅读(4432) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~