Linux编程学习(续二)

信号处理

信号相当于DOS下的Int或者Windows下的消息。

Kill –l命令可以查看各种信号信息。

man 7 signal可查看各个信号的具体解释。

软件原因和硬件原因都会产生信号。

常用的发信号的函数包括:

kill

raise

alarm

setitimer

killpid_t pid , int sig

调用kill可以向任何进程组或者进程发送任何信号。

Raise用来向自己发送信号sig,它等于killgetpid(),sig

Alarm函数在seconds秒后向自己发送一个SIGALRM信号。比如下面程序:

#include <stdio.h>

#include <unistd.h>

main()

{

unsigned int i;

alarm(1);

for(i = 0; 1 ; i++)

printf("I = %d",i);

}

SIGALRM的缺省操作是结束进程,因此1秒钟以后,你可以看到最后的I值是多少。

使用信号屏蔽可以使进程不受到信号的打扰。信号屏蔽用到几个函数:

int sigemptyset(sigset_t *set);

int sigfillset(sigset_t *set);

int sigaddset(sigset_t *set,int signo);

int sigdelset(sigset_t *set,int signo);

int sigismember(sigset_t *set,int signo);

int sigprocmask(int how,const sigset_t *set,sigset_t *oset);

下面例子演示了函数的使用:

#include <stdio.h>

#include <signal.h>

#include <stdlib.h>

int main(int argc,char **argv)

{

double y;

sigset_t intmask;

int i;

int repeat_factor;

if(argc != 2)

{

fprintf(stderr,"Usage:%s repeat_factor\n\a",argv[0]);

exit(1);

}

if((repeat_factor = atoi(argv[1])) < 1)

repeat_factor = 10;

sigemptyset(&intmask); //Initializes the signal set given by set to empty.

sigaddset(&intmask,SIGINT); //Add signal of INT Ctrl+C

while(1)

{

//Block signal and no saveed signal set.

sigprocmask(SIG_BLOCK,&intmask,NULL);

fprintf(stderr,"SIGINT signal blocked\n");

for(i = 0; i<repeat_factor ; i++)

fprintf(stderr,"blocked calculation is finished\n");

//UnBlock signal

sigprocmask(SIG_UNBLOCK,&intmask,NULL);

fprintf(stderr,"SIGINT signal unblocked\n");

for(i = 0; 1<repeat_factor ; i++)

fprintf(stderr,"Unblocked calculation is finished\n");

}

exit(0);

}

另一个有用的函数是sigaction,用来指定一个信号的处理行为。下面例子捕捉CtrlC的信号,并输出一个提示。

//function sigaction test.

#include <stdio.h>

#include <signal.h>

#include <stdlib.h>

#include <unistd.h>

#include <errno.h>

#define PROMPT "Do you want to exit this program?"

char * prompt = PROMPT;

void ctrl_c_op(int signo)

{

write(STDERR_FILENO,prompt,strlen(prompt));

}

int main(int argc,char **argv)

{

struct sigaction act;

act.sa_handler = ctrl_c_op;

sigemptyset(&act.sa_mask);

act.sa_flags = 0;

if(sigaction(SIGINT,&act,NULL) < 0)

{

fprintf(stderr,"Install Signal Action Error:%s\n\a",strerror(errno));

exit(1);

}

while(1);

exit(0);

}

还有一些很用于的关于信号方面的函数,比如:

pause

sigsuspend

sigsetjmp

siglongjmp

上面一些函数对于信号处理来说能够应付一般需要,其实信号的处理远非这些。

PS命令,列举当前系统中的进程信息

PS –A

Manwhatisapropos

Man命令是Linux下常用的参考文档。有两个配合使用的命令,就是whatis和。Aproposwhatis是全匹配,apropos是关键字匹配。比如,manager这个词,如果“whatis man”,就匹配不到,但apropos man则能够匹配到。

查找运行时的权能

sysconf函数用来查询运行时的权能。比如,对传递给一个新程序的字符串参数的长度进行限制,可以保护系统不被任意分配内存的要求所破坏。比如下面代码:

#include <stdio.h>

#include <unistd.h>

main()

{

printf("The number of clock ticks per second: %d\n",sysconf(_SC_CLK_TCK));

printf("The maximum length of the arguments to the exec() family of functions: %d\n",sysconf(_SC_ARG_MAX));

printf("The maximum number of files that a process can have open at any time: %d\n",sysconf(_SC_OPEN_MAX));

exit(0);

}

查找和设置系统的基本信息

使用uname函数。

Bug测试和调试

下面是一段测试代码,代码破坏了三种内存区域:

l malloc从动态内存池中分配的内存

l 在程序堆上分配的本地变量

l 在程序启动时候被静态分配的并保存在分散内存区域中的全局变量

#include <stdlib.h>

#include <stdio.h>

#include <string.h>

char global[5];

int broken(void)

{

char * dyn;

char local[5];

dyn = malloc(5);

strcpy(dyn,"12345");

printf("1: %s \n",dyn);

free(dyn);

dyn = malloc(5);

strcpy(dyn,"12345678");

printf("2: %s \n",dyn);

*(dyn - 1) = '\0';

printf("3: %s \n",dyn);

strcpy(local,"12345");

printf("4: %s \n",local);

local[-1] = '\0';

printf("5: %s \n",local);

strcpy(global,"12345");

printf("6: %s \n",global);

global[-1] = '\0';

printf("7: %s \n",global);

return 0;

}

int main(void)

{

return broken();

}

尽管从代码中已经发现问题,但实际上程序运行得很好。下面是结果。

<shapetype id="_x0000_t75" stroked="f" filled="f" path="m@4@5l@4@11@9@11@9@5xe" o:preferrelative="t" o:spt="75" coordsize="21600,21600"><stroke joinstyle="miter"></stroke><formulas><f eqn="if lineDrawn pixelLineWidth 0"></f><f eqn="sum @0 1 0"></f><f eqn="sum 0 0 @1"></f><f eqn="prod @2 1 2"></f><f eqn="prod @3 21600 pixelWidth"></f><f eqn="prod @3 21600 pixelHeight"></f><f eqn="sum @0 0 1"></f><f eqn="prod @6 1 2"></f><f eqn="prod @7 21600 pixelWidth"></f><f eqn="sum @8 21600 0"></f><f eqn="prod @7 21600 pixelHeight"></f><f eqn="sum @10 21600 0"></f></formulas><path o:connecttype="rect" gradientshapeok="t" o:extrusionok="f"></path><lock aspectratio="t" v:ext="edit"></lock></shapetype><shape id="_x0000_i1025" style="WIDTH: 364.5pt; HEIGHT: 123pt" type="#_x0000_t75"><imagedata o:title="001" src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msoclip1/01/clip_image001.jpg"></imagedata></shape>

为了发现问题,需要借助调试工具:

MALLOC_CHECK_,工具用于进行堆数据结构得一致性检查。有几种调试参数:

MALLOC_CHECK_=0 ./broken

MALLOC_CHECK_=1 ./broken

MALLOC_CHECK_=2 ./broken

最有用的是最后一句,一旦发现错误,工具将把我们带到错误发生点最近的地方。

这样用则更好:

$ MALLOC_CHECK_2 gdb ./broken

下面是部分调试信息:

GNU gdb Red Hat Linux (5.3post-0.20021129.18rh)

Copyright 2003 Free Software Foundation, Inc.

GDB is free software, covered by the GNU General Public Licen se, and you are

welcome to change it and/or distribute copies of it under cer tain conditions.

Type "show copying" to see the conditions.

There is absolutely no warranty for GDB. Type "show warranty " for details.

This GDB was configured as "i386-redhat-linux-gnu"...

(gdb) r

Starting program: /home/lx/csource/bugtest/broken

1: 12345

Program received signal SIGABRT, Aborted.

0xffffe002 in ?? ()

(gdb) where

#0 0xffffe002 in ?? ()

#1 0x42028a73 in abort () from /lib/tls/libc.so.6

#2 0x42075e09 in free_check () from /lib/tls/libc.so.6

#3 0x42073485 in free () from /lib/tls/libc.so.6

#4 0x0804840b in broken ()

#5 0x08048500 in main ()

#6 0x42015574 in __libc_start_main ()

from /lib/tls/libc.so.6

(gdb)

另一种调试方法是链接mcheck库函数,方法是:

[lx@ssss bugtest]$ gcc -ggdb -o broken broken.c -lmcheck

[lx@ssss bugtest]$ ./broken

1: 12345

memory clobbered past end of allocated block

mcheck只能打印错误信息,并不能指明错误所在,因此需要在gdb内运行程序。

版本问题

带奇数的内核版本(即 2.32.52.7 等)是实验性的开发版内核。稳定的发行版内核的版本号是偶数(即 2.42.62.8 等)。

=待续=

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值