用man 7 signal可查看各个信号的具体解释。
软件原因和硬件原因都会产生信号。
常用的发信号的函数包括:
kill
raise
alarm
setitimer
kill(pid_t pid , int sig)
调用kill可以向任何进程组或者进程发送任何信号。
Raise用来向自己发送信号sig,它等于kill(getpid(),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,用来指定一个信号的处理行为。下面例子捕捉Ctrl+C的信号,并输出一个提示。
//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
Man、whatis和apropos
Man命令是Linux下常用的参考文档。有两个配合使用的命令,就是whatis和。Apropos。whatis是全匹配,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.3、2.5、2.7 等)是实验性的开发版内核。稳定的发行版内核的版本号是偶数(即 2.4、2.6、2.8 等)。
=待续=
相关推荐
在Linux环境下进行C编程是一项基础且重要的技能,尤其在服务器端和嵌入式系统开发中。...以上是Linux环境下进行C编程所需掌握的关键知识点,通过深入学习和实践,你将能够编写出高效、稳定且适应各种Linux系统的C程序。
本设计实现了ftp的设计,使用了socket网络编程,ftp基于cs模式,包含客户端和服务端,可以实现上传、下载、删除、...运行环境是linux,压缩包内含有源代码、使用说明、实验报告等,是学习linux和网络编程的上等材料。
在给定的压缩包文件"ftp"中,可能包含了实现这些功能的C源代码,供学习和参考。通过阅读和分析这些代码,可以深入了解FTP客户端的工作原理和C语言在网络编程中的应用。不过,为了实现更高级的功能,如断点续传,需要...
【标题】:“基于UDP协议的Client/Server Linux网络编程” 在计算机网络中,UDP(User Datagram Protocol,用户数据报协议)是一种无连接的传输层协议,它提供了比TCP(Transmission Control Protocol,传输控制...
全书目录在本压缩包内。 本书共分五部分,详细介绍了shell编程技巧,各种UNIX命令及语法,还涉及了UNIX下的文字处理以及少量的系统管理问题。本书内容全面、文字简洁流畅,适合Shell编程人员学习、参考。
### 从Windows转向Linux...以上内容覆盖了从Windows转向Linux的过程中所需要掌握的基本知识点,不仅包括了操作系统本身的使用,还涉及到了软件安装、网络配置、编程开发等多个方面,为初学者提供了一个全面的学习指南。
通过研究这些源代码,开发者不仅可以深入理解DHCP协议,还可以学习到网络编程、系统级编程、多线程编程等多个领域的知识,对于提升自身的技能水平大有裨益。同时,这也为定制化DHCP服务器、开发相关工具或修复潜在...
#### 二、嵌入式Linux应用开发 **2.1 国嵌课程2-嵌入式Linux应用开发班** - **第1天(编程基础)** - **GCC程序编译**: 讲解如何使用GCC编译器编译C/C++程序。 - **GDB程序调试**: 教授如何使用GDB进行程序调试...
在Linux环境下,Socket编程是构建网络应用程序的基础,它允许程序之间通过网络进行通信。FTP(File Transfer Protocol)是一种用于在互联网上进行文件传输的标准协议。本教程将介绍如何使用Linux的socket API来实现...
本文将探讨dhcp-3.1.1版本的源码,通过分析源码,我们可以学习到Linux网络编程、TCP/IP协议栈和DHCP协议的细节。 1. **DHCP协议基础** DHCP协议基于UDP,使用客户端/服务器模型。在Linux环境下,DHCP服务端通常...
在Linux系统中,Socket编程是实现网络通信的一种基础方式,它可以...总之,这个项目涉及到Linux Socket编程的核心概念,包括连接建立、文件传输和断点续传的实现,对于理解和实践网络编程以及文件传输具有很高的价值。
**第11章 嵌入式Linux设备驱动开发(续)** 这部分进一步探讨中断处理、DMA(直接存储器访问)、设备驱动框架,以及如何调试驱动程序。 **第12章 Qt图形编程** Qt是一个流行的跨平台GUI库,适合在嵌入式设备上创建...
对于初学者,可以从中学习到C语言在Linux环境下的文件操作和网络编程知识;对于有经验的开发者,可以借鉴其中的实现策略,改进自己的代码。 由于没有具体的源码可供分析,以上内容是对基于C语言的Linux文件传输程序...
综上所述,“网络编程之文件服务器.rar”可能包含了创建文件服务器的源代码、文档或者示例,这些内容可以帮助开发者学习如何在Linux环境下构建一个支持断点续传功能的网络文件服务器。通过深入研究和实践,不仅可以...
- **中级阶段**:深入学习Linux内核、设备驱动等。 - **高级阶段**:项目实战、性能优化等。 **4. 嵌入式Linux入门学习内容指南** - **操作系统原理**:了解Linux内核架构。 - **编程技术**:学习C语言和Shell脚本...
在Linux操作系统中,FTP...总结,这个压缩包可能包含了Linux环境下使用FTP的相关教程、源代码示例,对于学习FTP的使用、实现及安全配置具有很高的价值。通过深入学习和实践,可以提升在Linux系统中进行文件传输的能力。
在Linux操作系统中,FTP(File Transfer Protocol)是一种用于在计算机之间传输文件的标准网络协议。它允许用户通过命令行界面或...通过阅读和分析这些代码,可以增强对网络协议和Linux编程的理解,提高问题解决能力。
以上只是LinuxTool项目中一小部分工具和命令的介绍,实际内容可能更丰富,包括但不限于文件压缩与解压缩、权限管理、脚本编程等方面。通过学习和熟练运用这些工具,可以在Linux环境中更加得心应手。对于开发者而言,...
这个名为"LinuxPPT.rar"的压缩包文件包含了深入学习Linux操作系统的丰富资源,涵盖了从基础到进阶的多个主题,适合对Linux感兴趣的初学者和希望提升技能的IT从业者。 首先,"第1章认识Linux.pptx"介绍了Linux的历史...