Linux高级编程--11.信号

基本概念信号在Linux中是一个比较常见的概念,例如我们按Ctrl+C中断前台进程,通过Kill命令结束进程都是通过信号实现的。下面就以Ctrl+C为例简单的说明信号的处理流程:用户按下Ctrl-C,这个键盘输入产生一个硬件中断。该进程的用户空间代码暂停执行,CPU从用户态切换到内核态处理硬件中断。终端驱动程序将Ctrl-C解释成一个SIGINT信号,记在该进程的PCB中(也可以说发送了一个SIGINT信号给该进程)。当内核返回到该进程的用户空间代码继续执行之前,首先处理PCB中记录的信号,发现有一个SIGINT信号待处理,而这个信号的默认处理动作是终止进程,所以直接终止进程而不再返回它的用户空间代码执行。用kill-l命令可以察看系统定义的信号列表:$kill–l1)SIGHUP2)SIGINT3)SIGQUIT4)SIGILL5)SIGTRAP6)SIGABRT7)SIGBUS8)SIGFPE9)SIGKILL10)SIGUSR111)SIGSEGV12)SIGUSR213)SIGPIPE14)SIGALRM15)SIGTERM16)SIGSTKFLT17)SIGCHLD18)SI...

Linux高级编程--10.Socket编程

Linux下的Socket编程大体上包括TcpSocket、UdpSocket即RawSocket这三种,其中TCP和UDP方式的Socket编程用于编写应用层的socket程序,是我们用得比较多的,而RawSocket则用得相对较少,不在本文介绍范围之列。TCPSocket基于TCP协议的客户端/服务器程序的一般流程一般如下:它基本上可以分为三个部分:一、建立连接:服务器调用socket()、bind()、listen()完成初始化后,调用accept()阻塞等待,处于监听端口的状态客户端调用socket()初始化后,调用connect()发出SYN段并阻塞等待服务器应答服务器应答一个SYN-ACK段,客户端收到后从connect()返回,同时应答一个ACK段,服务器收到后从accept()返回。二、传输数据:建立连接后,TCP协议提供全双工的通信管道,服务器端和客户端根据协议可以通过read和write的反复调用实现数据的传输三、关闭连接:当数据传输已经完成后,服务器和客户端可以调用Close关闭连接,一端关闭连接后,另一端read函数则会返回0,可以根据这个特征来感应另一端的退出...

Linux高级编程--09.线程互斥与同步

多个线程同时访问共享数据时可能会冲突,比如两个线程都要把某个全局变量增加1,这个操作在某平台需要三条指令完成:从内存读变量值到寄存器寄存器的值加1将寄存器的值写回内存假设两个线程在多处理器平台上同时执行这三条指令,则可能导致下图所示的结果,最后变量只加了一次而非两次。如下例子就演示了这一过程:#include<stdio.h>#include<pthread.h>#include<unistd.h>intcounter;/*incrementedbythreads*/void*doit(void*vptr){inti,val;for(i=0;i<100;i++){val=counter;usleep(1000);counter=val+1;}returnNULL;}intmain(intargc,char**argv){pthread_ttidA,tidB;pthread_create(&tidA,NULL,&doit,NULL);pthread_create(&tidB,NULL,&doit,NULL);pth...

Linux高级编程--08.线程概述

线程有的时候,我们需要在一个基础中同时运行多个控制流程。例如:一个图形界面的下载软件,在处理下载任务的同时,还必须响应界面的对任务的停止,删除等控制操作。这个时候就需要用到线程来实现并发操作。和信号处理函数的控制在处理完信号之后就结束不同的是,多线程的控制流程可以长期并存,操作系统会在各线程之间调度和切换,就像在多个进程之间调度和切换一样,但创建线程开销要比进程小得多。因此,线程往往也被称作轻量级的进程。由于同一进程的多个线程共享同一地址空间,数据段是共享的,如果定义一个全局变量,在各线程中都可以访问到。但有,些资源依然是每个线程各有一份的:线程id上下文,包括各种寄存器的值、程序计数器和栈指针栈空间errno变量信号屏蔽字调度优先级我们一般用到的是由POSIX标准定义的线程库函数,称为POSIXthread或者pthread。在Linux线程函数位于libpthread共享库中,因此在编译时要加上-lpthread选项。创建线程在POSIX库中,创建线程是通过函数实现的,它的声明如下:#include<pthread.h>intpthread_create(pthrea...

Linux高级编程--07.进程间通信

每个进程各自有不同的用户地址空间,进程之间要交换数据必须通过在内核中开辟缓冲区,从而实现数据共享。管道管道是一种最基本的IPC机制,由pipe函数创建:intpipe(intfiledes[2]);调用pipe函数时在内核中开辟一块缓冲区(称为管道)用于通信,它有一个读端一个写端,然后通过filedes参数传出给用户程序两个文件描述符,filedes[0]指向管道的读端,filedes[1]指向管道的写端(很好记,就像0是标准输入1是标准输出一样)。所以管道在用户程序看起来就像一个打开的文件,通过read(filedes[0]);或者write(filedes[1]);向这个文件读写数据其实是在读写内核缓冲区。一个基本示例如下:#include<stdlib.h>#include<unistd.h>#defineMAXLINE80intmain(void){intn;intfd[2];pid_tpid;charline[MAXLINE];if(pipe(fd)<0){perror("pipe");exit(1);}if((pid=fork())<0)...

Linux高级编程--06.进程概述

进程控制块在Linux中,每个进程在内核中都有一个进程控制块(PCB)来维护进程相关的信息,它通常包含如下信息:进程id。系统中每个进程有唯一的id,在C语言中用pid_t类型表示,其实就是一个非负整数。进程的状态,有运行、挂起、停止、僵尸等状态。进程切换时需要保存和恢复的一些CPU寄存器。描述虚拟地址空间的信息。描述控制终端的信息。当前工作目录(CurrentWorkingDirectory)。umask掩码。文件描述符表,包含很多指向file结构体的指针。和信号相关的信息。用户id和组id。控制终端、Session和进程组。进程可以使用的资源上限(ResourceLimit)。fork和execfork的作用是根据一个现有的进程复制出一个新进程,原来的进程称为父进程(ParentProcess),新进程称为子进程(ChildProcess)。系统中同时运行着很多进程,这些进程都是从最初只有一个进程开始一个一个复制出来的。在Shell下输入命令可以运行一个程序,是因为Shell进程在读取用户输入的命令之后会调用fork复制出一个新的Shell进程,然后新的Shell进程调用exec执...

Linux高级编程--05.文件读写

缓冲I/O和非缓冲I/O文件读写主要牵涉到了如下五个操作:打开、关闭、读、写、定位。在Linux系统中,提供了两套API,一套是C标准API:fopen、fclose、fread、fwrite、fseek,另一套则是POSIX定义的系统API:open、close、read、write、seek。其中POSIX定义的API是系统API,而C标准API是基于系统API的封装,并且提供了额外的缓冲的功能。因此也可以把它们叫做缓冲I/O函数和非缓冲I/O函数。除了前面介绍的这几个缓冲IO函数外,C标准库里面还提供了一系列封装的IO函数:如puts、putchar、printf等。为什么要有增加缓冲区这个功能呢?主要是因为IO操作时,操作系统要从用户态转换为内核态的,而这个转换过程相对来说比较慢,因此可以通过缓冲的形式减少转换到内核态的次数。那么,缓冲IO函数又是如何工作的呢?当用fopen打开文件时,除了分配文件句柄外,还额外申请了一个缓冲区。读文件时,会首先读到缓冲区中,然后返回用户需要的部分,多余的部分仍然放在缓冲区,下次再读的时候可以直接从缓冲区中返回。写文件时,会先写到缓冲区中,等缓...

Linux高级编程--04.GDB调试程序(查看数据)

查看栈信息当程序被停住了,你需要做的第一件事就是查看程序是在哪里停住的。当你的程序调用了一个函数,函数的地址,函数参数,函数内的局部变量都会被压入“栈”(Stack)中。你可以用GDB命令来查看当前的栈中的信息。下面是一些查看函数调用栈信息的GDB命令:backtrace/bt:打印当前的函数调用栈的所有信息。如:(gdb)bt#0func(n=250)attst.c:6#10x08048524inmain(argc=1,argv=0xbffff674)attst.c:30#20x400409edin__libc_start_main()from/lib/libc.so.6从上可以看出函数的调用栈信息:__libc_start_main–>main()–>func()backtrace/bt:n是一个正整数,表示只打印栈顶上n层的栈信息。backtrace<-n>/bt<-n>:-n表一个负整数,表示只打印栈底下n层的栈信息。如果你要查看某一层的信息,你需要在切换当前的栈,一般来说,程序停止时,最顶层的栈就是当前栈,如果你要查看栈下面层的详细信息,首...

Linux高级编程--04.GDB调试程序(设置断点)

调试已运行的程序在UNIX下用ps查看正在运行的程序的PID(进程ID),然后用gdbPID格式挂接正在运行的程序。先用gdb关联上源代码,并进行gdb,在gdb中用attach命令来挂接进程的PID。并用detach来取消挂接的进程。暂停/恢复程序运行调试程序中,暂停程序运行是必须的,GDB可以方便地暂停程序的运行。你可以设置程序的在哪行停住,在什么条件下停住,在收到什么信号时停往等等。以便于你查看运行时的变量,以及运行时的流程。当进程被gdb停住时,你可以使用infoprogram来查看程序的是否在运行,进程号,被暂停的原因。在gdb中,我们可以有以下几种暂停方式:断点(BreakPoint)、观察点(WatchPoint)、捕捉点(CatchPoint)、信号(Signals)、线程停止(ThreadStops)。如果要恢复程序运行,可以使用c或是continue命令。设置断点(BreakPoint)我们用break命令来设置断点。正面有几点设置断点的方法:break:在进入指定函数时停住。C++中可以使用class::function或function(type,type)格式...

Linux高级编程--04.GDB调试程序(入门概述)

GDB概述GDB是GNU开源组织发布的一个强大的UNIX下的程序调试工具。或许,各位比较喜欢那种图形界面方式的,像VC、BCB等IDE的调试,但如果你是在UNIX平台下做软件,你会发现GDB这个调试工具有比VC、BCB的图形化调试器更强大的功能。所谓“寸有所长,尺有所短”就是这个道理。一般来说,GDB主要帮忙你完成下面四个方面的功能:启动你的程序,可以按照你的自定义的要求随心所欲的运行程序。可让被调试的程序在你所指定的调置的断点处停住。(断点可以是条件表达式)当程序被停住时,可以检查此时你的程序中所发生的事。动态的改变你程序的执行环境。从上面看来,GDB和一般的调试工具没有什么两样,基本上也是完成这些功能,不过在细节上,你会发现GDB这个调试工具的强大,大家可能比较习惯了图形化的调试工具,但有时候,命令行的调试工具却有着图形化工具所不能完成的功能。让我们一一看来。一个调试示例//test.c#include<stdio.h>intfunc(intn){intsum=0,i;for(i=0;i<n;i++){sum+=i;}returnsum;}intmain(){in...

Linux高级编程--03.make和makfile

Makefile语法基础在Linux下,自动化编译工具是通过make命令来完成的(一些工具厂商也提供了它们自己的make命令,如gmake等),make命令的基本格式如下:make[-fmakefile][label]它可以通过-f参数指定输入文件,当省略-f参数时,默认输入文件名为Makefile,由于我们通常不用这个-f参数,往往就用默认的Makefile文件名。Makefile是一个文本文件,它是基于一定的语法规则的,它的基本执行规则定义如下:target:[prerequisites]commandtarget:标签,用于标志当前构建的规则,它也可以是文件。prerequisites:依赖项,在构建该标签的时候先执行的规则commandmake:需要执行的命令。(任意的Shell命令)注意:Makefile的target是顶格写的,而Command需要加一个Tab键。例如,我们编写一个简单的Makefile:clean:@echo"clean"all:@echo"all"当我们直接执行make命令的时候,输出如下:$makeclean$makeallall$makecleanc...

Linux高级编程--02.gcc和动态库

Linux环境下,我们通常用gcc将C代码编译成可执行文件,如下就是一个简单的例子:小实验:hello.c#include<stdlib.h>#include<stdio.h>voidmain(void){printf("helloworld!");}可以通过如下指令来编译出一个可执行文件:gcchello.c执行完该命令后,就会得到一个a.out的可执行文件。编译的过程前面的例子只是简单的介绍了一下gcc的使用方法,熟悉c编程的朋友就会知道,该步骤其实包含了预处理–>编译–>汇编–>链接四步,这四步分别实现的功能如下:预处理阶段:主要处理源文件中的#ifdef、#include和#define命令,展开宏、读取定义的符号等(.i)编译阶段:检查代码的规范性,把代码翻译成汇编语言(.s)汇编阶段:是把编译阶段生成的文件转成二进制目标代码(.o)链接阶段:将汇编阶段生成的机器码汇集成一个可执行的二进制代码文件由此可以看出,每一个阶段的输出其实就是下一个阶段的输入,用gcc是可以单独执行这四步的:gcc-Ehello.c-ohello.igcc-...

Linux高级编程--01.vi命令

VI是Linux/Unix下标配的一个纯字符界面的文本编辑器。由于不支持鼠标功能,也没有图形界面,相关的操作都要通过键盘指令来完成,需要记忆大量命令。因此很多人不大喜欢它,但同时由于键盘的方式往往比鼠标来得快,一旦熟练后用起来是有种非常流畅的感觉的,也有人因此而非常喜欢它。不管你喜欢也好,不喜欢也好,VI是Linux的标配编辑器,很多时候你也只有这一个编辑器可用,如果要做一个LinuxCoder,熟悉VI还是非常有必要的。PS:由于VI的命令非常多,本文主要只介绍一些基础命令。并且就算是这些基础命令中,也有许多是不大常用的,我就把这些命令以灰色文字显示了,初学者可以不用太关注这些灰色命令。两种工作模式前面已经说过,由于VI没有图形界面,如翻页、移动光标、保存、退出等操作都必须借助键盘来完成。另外,VI还提供了大量快捷键来加速操作,因此,VI统的编辑模式下,还引入了一种新的工作模式——命令模式。编辑模式:在此模式下,输入可见字符时和传统Windows环境下输入字符的功能相同。按Esc键可切换值命令模式。命令模式:在此模式下,输入的可见字符对应的是命令。当插入命令执行后进入编辑模式。PS:...

PHP扩展--opcache安装及配置

简介Optimizer+是Zend开发的闭源但可以免费使用的PHP优化加速组件,是第一个也是最快的opcode缓存工具。现在,Zend科技公司将Optimizer+在PHPLicense下开源成为ZendOpcache。ZendOPcache通过opcode缓存和优化提供更快的PHP执行过程。它将预编译的脚本文件存储在共享内存中供以后使用,从而避免了从磁盘读取代码并进行编译的时间消耗。同时,它还应用了一些代码优化模式,使得代码执行更快。当解释器完成对脚本代码的分析后,便将它们生成可以直接运行的中间代码,也称为操作码(OperateCode,opcode)。Opcodecache的目地是避免重复编译,减少CPU和内存开销。如果动态内容的性能瓶颈不在于CPU和内存,而在于I/O操作,比如数据库查询带来的磁盘I/O开销,那么opcodecache的性能提升是非常有限的。现代操作码缓存器(Optimizer+,APC2.0+,其他)使用共享内存进行存储,并且可以直接从中执行文件,而不用在执行前“反序列化”代码。这将带来显着的性能加速,通常降低了整体服务器的内存消耗,而且...

PHP扩展--Oracle客户端(oci8)安装

下载Oracle客户端官方下载地址:LinuxX86-64同意协议,下载以下文件:oracle-instantclient11.2-basic-11.2.0.4.0-1.x86_64.rpmoracle-instantclient11.2-devel-11.2.0.4.0-1.x86_64.rpm安装rpm-ivhoracle-instantclient11.2-basic-11.2.0.4.0-1.x86_64.rpmrpm-ivhoracle-instantclient11.2-devel-11.2.0.4.0-1.x86_64.rpmbasic默认安装在/usr/lib/oracle/下devel默认安装在/usr/include/oracle/下安装PHP扩展cdphp-5.3.3/ext/oci8phpizeexportLD_LIBRARY_PATH=/usr/lib/oracle/11.2/client64/:$LD_LIBRARY_PATHexportORACLE_HOME="/usr/lib/oracle/11.2/client64/"exportCFLAGS="-I/...
首页上一页...769770771772773...下一页尾页