📄 1041.html
字号:
<br>
Linux程式设计- 3.signals <br>
http://www.openchess.org/noitatsko/programming/ (2001-05-24 16:47:48) <br>
信号处理 <br>
<br>
-------------------------------------------------------------------------------- <br>
<br>
信号处理概说 <br>
送出信号 <br>
接收信号 <br>
信号的处理 <br>
任务控制 <br>
<br>
-------------------------------------------------------------------------------- <br>
<br>
POSIX IPC <br>
reliable/unreliable <br>
reentrant <br>
pending <br>
sending signals <br>
catching signals <br>
manipulating <br>
signal definitions <br>
<br>
-------------------------------------------------------------------------------- <br>
<br>
信号singals <br>
信号的处理可以用一大章来写,涉及的层面也会深入整个作业系统中,我并不打算这样做,因为您可能会越搞越迷糊。这里我只告诉您如何接上信号,在实用的层面上,这样便很够用了。您可以先利用这些基本的技巧来撰写程式,等到有进一步高等应用的需要时,找一本较深入的UNIX Programming教材,专门研究signal的写法。 <br>
一般简单的signal写法如下: <br>
<br>
void mysignal(int signo) <br>
{ <br>
/* my signal handler */ <br>
} <br>
<br>
void initsignal(void) <br>
{ <br>
struct sigaction act; <br>
<br>
act.sa_handler = mysignal; <br>
act.sa_flags = 0; <br>
sigemptyset(&act.sa_mask); <br>
sigaction(SIGHUP,&act,NULL); <br>
sigaction(SIGINT,&act,NULL); <br>
sigaction(SIGQUIT,&act,NULL); <br>
sigaction(SIGILL,&act,NULL); <br>
sigaction(SIGTERM,&act,NULL); <br>
} <br>
<br>
<br>
例一: lock.c <br>
在fork的例三中提到,在daemon被杀掉时,需要在离开前,将/var/run/lock.pid删除。这里我们可以利用signal来处理这件事。 <br>
#include <br>
#include <br>
#include <br>
#include <br>
<br>
#define LOCK_FILE "/var/run/lock.pid" <br>
<br>
void quit(int signo) <br>
{ <br>
printf("Receive signal %d",signo); <br>
unlink(LOCK_FILE); <br>
exit(1); <br>
} <br>
<br>
void main(void) <br>
{ <br>
FILE *fp; <br>
pid_t pid; <br>
struct sigaction act; <br>
<br>
if (access(LOCK_FILE,R_OK)==0) { <br>
printf("Existing a copy of this daemon!"); <br>
exit(1); <br>
} <br>
<br>
pid = fork(); <br>
<br>
if (pid>0) { <br>
printf("daemon on duty!"); <br>
<br>
fp = fopen(LOCK_FILE,"wt"); <br>
fprintf(fp,"%d",pid); <br>
fclose(fp); <br>
} else <br>
exit(0); if (pid<0) { <br>
printf("Can't fork!"); <br>
exit(-1); <br>
} <br>
<br>
act.sa_handler = quit; <br>
act.sa_flags = 0; <br>
sigemptyset(&act.sa_mask); <br>
sigaction(SIGTERM,&act,NULL); <br>
sigaction(SIGHUP,&act,NULL); <br>
sigaction(SIGINT,&act,NULL); <br>
sigaction(SIGQUIT,&act,NULL); <br>
sigaction(SIGUSR1,&act,NULL); <br>
sigaction(SIGUSR2,&act,NULL); <br>
<br>
for (;;) { <br>
sleep(3); <br>
} <br>
} <br>
<br>
编译: <br>
gcc -o ex1 lock.c <br>
执行 <br>
./ex1 <br>
daemon on duty! <br>
<br>
送信号 <br>
我们先找出该守护神程式的pid <br>
PID=`cat /var/run/lock.pid` <br>
<br>
接下来利用kill来送信号 <br>
<br>
kill $PID <br>
<br>
Receive signal 15 <br>
<br>
程式将会结束,并且/var/run/lock.pid将会被删除掉,以便下一次daemon再启动。注意到如果quit函数内,没有放exit(),程式将永远杀不掉。 <br>
<br>
接下来送一些其它的信号试试看。 <br>
./ex1 <br>
PID=`cat /var/run/lock.pid` <br>
kill -HUP $PID <br>
<br>
Receive signal 1 <br>
<br>
您可以自行试试 <br>
kill -INT $PID <br>
kill -QUIT $PID <br>
kill -ILL $PID <br>
. <br>
. <br>
. <br>
等等这些信号,看看他们的结果如何。 <br>
<br>
信号的定义 <br>
在/usr/include/signum.h中有各种信号的定义 <br>
#define SIGHUP 1 &nb <br>
<br>
<br>
Linux程式设计- 4.socket <br>
http://www.openchess.org/noitatsko/programming/ (2001-05-24 17:24:26) <br>
UNIX Socket Programming基本上是一本书名。Socket programming其实需要相当程度的基础,我不想在这包山包海地,如果您需要彻底研究,可以买这本书来看。在此我想提供一些简单的Server/Client两端的简单写法,让你有个起点,做为进一步研究的基础。很多涉及较复杂的内容的,我在这便不详细说明,您可以照本宣科,照抄着用,稍微熟悉时,再细细研究。 <br>
<br>
-------------------------------------------------------------------------------- <br>
<br>
Client <br>
int sock_connect(char *domain,int port) <br>
{ <br>
int white_sock; <br>
struct hostent * site; <br>
struct sockaddr_in me; <br>
site = gethostbyname(domain); <br>
if (site==NULL) return -2; <br>
<br>
white_sock = socket(AF_INET,SOCK_STREAM,0); <br>
if (white_sock<0) return -1; <br>
<br>
memset(&me,0,sizeof(struct sockaddr_in)); <br>
memcpy(&me.sin_addr,site->h_addr_list[0],site->h_length); <br>
me.sin_family = AF_INET; <br>
me.sin_port = htons(port); <br>
<br>
return (connect(white_sock,(struct sockaddr *)&me,sizeof(struct sockaddr))<0) ? -1 : white_sock; <br>
} <br>
<br>
要由Client向伺服器端要求连线的步骤,首先您必须要找出对方的位址,可利用: <br>
<br>
gethostbyname() <br>
<br>
接下来要建立起一个socket,然後用这个socket来建立连线。 <br>
<br>
接下来我们利用这个简单的socket程式来写一个读取WWW网页的简单浏览器(看html source)。 <br>
#include <br>
#include <br>
#include <br>
#include <br>
#include <br>
#include <br>
#include <br>
<br>
int htconnect(char *domain,int port) <br>
{ <br>
int white_sock; <br>
struct hostent * site; <br>
struct sockaddr_in me; <br>
<br>
site = gethostbyname(domain); <br>
if (site==NULL) return -2; <br>
<br>
<br>
white_sock = socket(AF_INET,SOCK_STREAM,0); <br>
if (white_sock<0) return -1; <br>
<br>
memset(&me,0,sizeof(struct sockaddr_in)); <br>
memcpy(&me.sin_addr,site->h_addr_list[0],site->h_length); <br>
me.sin_family = AF_INET; <br>
me.sin_port = htons(port); <br>
<br>
return (connect(white_sock,(struct sockaddr *)&me,sizeof(struct sockaddr))<0) ? -1 : white_sock; <br>
} <br>
<br>
int htsend(int sock,char *fmt,...) <br>
{ <br>
char BUF[1024]; <br>
va_list argptr; <br>
va_start(argptr,fmt); <br>
vsprintf(BUF,fmt,argptr); <br>
va_end(argptr); <br>
return send(sock,BUF,strlen(BUF),0); <br>
} <br>
<br>
void main(int argc,char **argv) <br>
{ <br>
int black_sock; <br>
char bugs_bunny[3]; <br>
<br>
if (argc<2) return; <br>
<br>
black_sock = htconnect(argv[1],80); <br>
if (black_sock<0) return; <br>
htsend(black_sock,"GET / HTTP/1.0%c",10); <br>
htsend(black_sock,"Host: %s%c",argv[1],10); <br>
htsend(black_sock,"%c",10); <br>
while (read(black_sock,bugs_bunny,1)>0) { printf("%c",bugs_bunny[0]); } <br>
<br>
close(black_sock); <br>
} <br>
<br>
编译: <br>
gcc -o ex1 client.c <br>
执行 <br>
./ex1 www.linux.org.tw <br>
<br>
<br>
-------------------------------------------------------------------------------- <br>
<br>
Server <br>
Listen to a port <br>
要建立起一个网路伺服器,第一步就是要"倾远方",也就是要Listen。 <br>
以下是一般建立服务的方法: <br>
int DaemonSocket; <br>
struct sockaddr_in DaemonAddr; <br>
int BindSocket(void) <br>
{ <br>
<br>
DaemonSocket = socket(AF_INET,SOCK_STREAM,0); <br>
if (DaemonSocket==-1) return 0; <br>
DaemonAddr.sin_family = AF_INET; <br>
DaemonAddr.sin_port = htons(DAEMON_PORT); <br>
if (bind(DaemonSocket,&DaemonAddr,sizeof(DaemonAddr))<0) { <br>
printf("Can not bind!"); <br>
return 0; <br>
} <br>
if (listen(DaemonSocket,1024)!=0) { <br>
printf("Can not listen!"); <br>
return 0; <br>
} <br>
<br>
return 1; <br>
} <br>
<br>
Incoming call <br>
要查看是否有连线进来,可用以下方式: <br>
int incoming_call(void) <br>
{ <br>
fd_set sock; <br>
struct timeval tv; <br>
int t; <br>
<br>
FD_ZERO(&sock); <br>
FD_SET(DaemonSocket,&sock); <br>
tv.tv_sec = 60; tv.tv_usec = 0; <br>
t = select(DaemonSocket + 1,&sock,NULL,NULL,&tv); <br>
if (t<=0||!FD_ISSET(DaemonSocket,&sock)) return 0; <br>
<br>
printf("incoming..."); <br>
<br>
return 1; <br>
} <br>
<br>
Connect Client <br>
当我们确认有人进来要求服务时,会需要accept connection,可用以下方式 <br>
int ConnectClient(void) <br>
{ <br>
int socksize=sizeof(HostAddr); <br>
unsigned char * addr; <br>
<br>
ClientSocket = accept(DaemonSocket,(struct sockaddr*)&HostAddr,&socksize); <br>
if (ClientSocket<0) return 0; <br>
<br>
addr = (unsigned char *)&HostAddr.sin_addr.s_addr; <br>
<br>
printf("incoming address:%d.%d.%d.%d",addr[0],addr[1],addr[2],addr[3]); <br>
<br>
return 1; <br>
} <br>
<br>
注意到当您accept connection之後,连线已建立起,此时要用的socket是ClientSocket,而非DaemonSocket,ClientSocket才是真正用来连线用的socket。 <br>
<br>
这是个我才刚开始动手写的象棋伺服器。 <br>
<br>
#include <br>
#include <br>
#include <br>
#include <br>
#include <br>
#include <br>
#include <br>
#include <br>
#include <br>
#include <br>
#include <br>
#include <br>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -