linux-socket编程使用到的函数总结

本文详细介绍了Linux系统中进程控制的几个关键函数:wait、waitpid、signal、kill及其使用方法,包括如何处理子进程结束、设置信号处理器、发送信号等,是理解Linux进程间通信与控制的基础。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1:wait

函数功能:父进程一旦调用wait函数,就会立即阻塞自己,由wait分析是否当前进程的某个子进程已经退出,如果让它找到了这样一个已经变成僵尸的子进程,wait就会收集这个子进程的信息,并把它彻底销毁返回,如果没有找到,就一直阻塞,直至找到一个结束的子进程或接收到了一个指定的信号为止。

2:waitpid

函数功能:waitpid()的作用和wait()函数一样,但它并不一定要等待第一个终止的子进程,它还有若干选项,如可提供一个非阻塞版本的wait()功能等。实际上wait()函数只是waitpid()函数的一个特例。

3:wait()与waitpid()函数的区别:

wait会令调用者阻塞直至某个子进程终止。waitpid则可以通过设置一个选项来设置为非阻塞,另外waitpid并不是等待第一个结束的进程而是等待参数中pid指定的进程。

函数原型:

#include<sys/wait.h>

pid_t wait(int * statloc);
pid_t waitpid(pid_t pid, int *statloc, int options);

成功返回进程ID,出错返回0或者-1。

waitpid的option常量:

WNOHANG waitpid将不阻塞如果指定的pid并未结束,

WUNTRACED 如果子进程进入暂时执行情况则马上返回,但结束状态不予理会。

waitpid中pid的含义依据其具体值而变:

pid == -1 等待任何一个子进程,此时waitpid的作用与wait相同。

pid > 0 等待进程ID与pid值相同的子进程。

pid==0 等待与调用者进程组ID相同的任意子进程。

pid<-1 等待进程组ID与pid绝对值相等的任意子进程。

waitpid提供了wait所没有的三个特性:

     waitpid使我们可以等待制定的进程。

     waitpid提供了一个无阻塞的wait

     waitpid支持工作控制

验证wait函数:

#include<sys/types.h>
#include<sys/wait.h>
#include<unistd.h>
#include<stdlib.h>

int main()
{
	pid_t pc, pc1;
	pc = fork();
	
	if(pc < 0)
	{
		printf("error!/n");
	}
	else if(pc == 0)
	{
		//sleep(10);
		printf("This is child process!/n");
		sleep(10);//为了验证wait函数的功能 
	}
	else
	{
		printf("This is Parent process! /n");
		pc1 = wait(NULL);
		printf("The child process pid == %d/n",pc1);
	}
	exit(0);
}
pc1 = wait(NULL);
如果成功,wait会返回被收集的子进程的进程ID,如果调用进程没有子进程,调用会失败,
此时wait返回-1.同时errno被置为ECHILD.

有关wait和waitpid函数介绍的好的博客:https://blog.youkuaiyun.com/kevinhg/article/details/7001719 

剩余后续更新

3:signal

功能:设置某一信号的对应动作

声明如下:

#include<signal.h>
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);

第一个参数signum:指明所要处理的信号类型,它可以取除了SIGKILL和SIGSTOP外的任何一种信号。

第二个参数handler:描述了与信号关联的动作,它可以取三种类型。

signal的定义原型是:
void (*signal(int signum, void (*func)(int))) (int)
这个函数的最外层的函数体为void(* xxx) (int);表明是一个指针,指向一个函数xxx的指针,XXX所代表的函数需要一个int参数,返回void

signal(int signum, void(*func)(int));
需要两个参数int型的signo以及一个指向函数的指针。正是由于其的复杂性,使用typedef来对其进行简化。
typedef void (*sighandler_t)(int);
所以原函数就可以改为:
sighandler_t signal(int , sighandler_t );
在使用的时候第一个参数代表信号,第二个参数代表接受到这个参数时所需要的进行的操作

对于第二个参数的理解:

(1) SIG_IGN  这个符号表示忽略该信号。

例子:
#include<stdio.h>
#include<signal.h>

int main()
{
    signal(SIGINT, SIG_IGN);
    while(1);
    return 0;
}
SIGINT信号代表有InterruptKey产生,通常是CTRL+C或者DELETE。执行上述代码时,按下CTRL+C程序没有反应。表示该信号被忽略。

(2)SIG_DFL 这个符号表示恢复对信号的系统默认处理。
程序:
#include <stdio.h>
#icnlude <signal.h>

int main()
{
    signal(SIGINT, SIG_DFL);
    while(1);
    return 0;
}
运行程序就可以使用CTRL+C来终止该程序。

(3)sighandler_t类型的函数指针
sighandler_t signal(int signum, sighandler_t handler);
次函数必须在signal()被调用之前申明。当接收到一个类型为sig的信号时,就执行handler所指定的函数。 int signum是传递给它的唯一参数。执行signal()调用后,进程只要接收到类型为sig的信号,不管其正在执行程序的哪一部分,就立即执行handler函数。当handler函数执行结束后,控制权返回进程被中断的哪一点继续执行。
程序:
#include <stdio.h>
#include <signal.h>
typedef void (*signal_handler)(int);
 
void signal_handler_fun(int signum) {
    printf("catch signal %d\n", signum);
}
 
int main(int argc, char *argv[]) {
    signal(SIGINT, signal_hander_fun);
    while(1);
    return 0;
}

当一个信号的信号处理函数执行时,如果进程又接收到了该信号,该信号会自动被储存而不会中断信号处理函数的执行,直到信号处理函数执行完毕再重新调用相应的处理函数。但是如果在信号处理函数执行时进程收到了其它类型的信号,该函数的执行就会被中断。

一些常使用的signal:

Signal    Description
SIGABRT   由调用abort函数产生,进程非正常退出

SIGALRM 

用alarm函数设置的timer超时或setitimer函数设置的interval timer超时
SIGBUS    某种特定的硬件异常,通常由内存访问引起
SIGCANCEL  由Solaris Thread Library内部使用,通常不会使用
SIGCHLD   进程Terminate或Stop的时候,SIGCHLD会发送给它的父进程。缺省情况下该Signal会被忽略
SIGCONT    当被stop的进程恢复运行的时候,自动发送
SIGEMT   和实现相关的硬件异常
SIGFPE   数学相关的异常,如被0除,浮点溢出,等等
SIGFREEZE   Solaris专用,Hiberate或者Suspended时候发送
SIGHUP   发送给具有Terminal的Controlling Process,当terminal 被disconnect时候发送
SIGILL    非法指令异常
SIGINT 由Interrupt Key产生,通常是CTRL+C或者DELETE。发送给所有ForeGround Group的进程
SIGIO   异步IO事件
SIGIOT    实现相关的硬件异常,一般对应SIGABRT
SIGKILL    无法处理和忽略。中止某个进程
SIGLWP   由Solaris Thread Libray内部使用
SIGPIPE   在reader中止之后写Pipe的时候发送
SIGPOLL   当某个事件发送给Pollable Device的时候发送
SIGPROF   Setitimer指定的Profiling Interval Timer所产生
SIGPWR    和系统相关。和UPS相关。
SIGQUIT   输入Quit Key的时候(CTRL+\)发送给所有Foreground Group的进程
SIGSEGV   非法内存访问
SIGSTKFLT   Linux专用,数学协处理器的栈异常
SIGSTOP   中止进程。无法处理和忽略。
SIGSYS    非法系统调用
SIGTERM   请求中止进程,kill命令缺省发送
SIGTHAW   Solaris专用,从Suspend恢复时候发送
SIGTRAP   实现相关的硬件异常。一般是调试异常
SIGTSTP   Suspend Key,一般是Ctrl+Z。发送给所有Foreground Group的进程
SIGTTIN    当Background Group的进程尝试读取Terminal的时候发送
SIGTTOU   当Background Group的进程尝试写Terminal的时候发送
SIGURG   当out-of-band data接收的时候可能发送
SIGUSR1    用户自定义signal 1
SIGUSR2    用户自定义signal 2
SIGVTALRM  setitimer函数设置的Virtual Interval Timer超时的时候
SIGWAITING   Solaris Thread Library内部实现专用
SIGWINCH   当Terminal的窗口大小改变的时候,发送给Foreground Group的所有进程
SIGXCPU    当CPU时间限制超时的时候
SIGXFSZ   进程超过文件大小限制
SIGXRES    Solaris专用,进程超过资源限制的时候发

4:kill

int kill(pid_t pid, int sig);

pid:可能选择由以下四种
1. pid大于零时,pid是信号欲送往的进程的标识
2. pid等于零时,信号将送往所有与调用kill()的那个进程属同一个使用组的进程。
3. pid等于-1时,信号将送往所有调用进程有权给其发送信号的进程,除了进程1(init)。
4. pid小于-1时,信号将送往以-pid为组标识的进程。
sig:准备发送的信号代码,假如其值为零则没有任何信号送出,但是系统会执行错误检查,通常会利用sig值为零来检验某个进程是否仍在执行。
返回值说明: 成功执行时,返回0。失败返回-1,errno被设为以下的某个值 EINVAL:指定的信号码无效(参数 sig 不合法) EPERM;权限不够无法传送信号给指定进程 ESRCH:参数 pid 所指定的进程或进程组不存在
代码:
#include <sys/wait.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

int main( void )
{
    pid_t childpid;
    int status;
    int retval;

    childpid = fork();
    if ( -1 == childpid )
    {
        perror( "fork()" );
        exit( EXIT_FAILURE );
    }
    else if ( 0 == childpid )
    {
        puts( "In child process" );
        sleep( 100 );//让子进程睡眠,看看父进程的行为
        exit(EXIT_SUCCESS);
    }
    else
    {
        if ( 0 == (waitpid( childpid, &status, WNOHANG )))
        {
            retval = kill( childpid,SIGKILL );

            if ( retval )
            {
                puts( "kill failed." );
                perror( "kill" );
                waitpid( childpid, &status, 0 );
            }
            else
            {
                printf( "%d killed\n", childpid );
            }

        }
    }

    exit(EXIT_SUCCESS);
}

5:recv

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值