Linux下进程控制函数
来源:互联网 发布:sql constraint 编辑:程序博客网 时间:2024/05/16 11:01
在Linux中shell命令中 ps查看几个进程;ps -aux每一进程详细信息
获取进程ID
#include<sys/types.h>
#include<unistd.h>
pid_t getpid(void)
pid_t 非负整数,0表示调度进程
派生子进程
#include<sys/types.h>
#include<unistd.h>
pid_t fork(void)
//拷贝父进程数据段
出错-1(进程数上限,或系统内存不足)
成功
父进程返回子进程ID
子进程返回0
(fork仅被调用一次)
派生子线程
#include<sys/types.h>
#include<unistd.h>
pid_t vfork(void)
//调用exec或exit前共享数据段
//等待子进程exit(1)才执行父进程
出错-1(进程数上限,或系统内存不足)
成功
父进程返回子进程ID
子进程返回0
(fork仅被调用一次)
exec函数族
#include <unistd.h>
int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg, ..., char *const envp[]);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execve(const char *path, char *const argv[], char *const envp[]);
p:file可执行文件名
e:envp子进程环境变量
path程序路径
可执行文件:二进制文件,Linux下的脚本文件
成功无返回,失败-1
const char*arg :"ls","-l"……NULL
char*const str={"ls","-l",NULL}
char*const argv[]:str
char*const ev={"HOME=this","PATH=hah",NULL}
char*const envp[]环境变量NULL结束
写时复制
#include<stdio.h>
void perror(const char*s)
#include<stdio.h>
void exit(int status)
保证数据完整性
0进程正常结束,其他非正常
#include<unistd.h>
void _exit(int status)
缓冲区数据丢失
#include<sys/types.h>
#include<sys/wait.h>
pid_t wait(int*status)
#include<sys/types.h>
#include<sys/wait.h>
pid_t waitpid(pid_t pid,int*status,int options)
pid>0等待子进程ID=pid
pid=-1等待任一子进程
pid=0等待同进程组的任何子进程
pid<-1等待指定进程组任何子进程ID=|pid|
#include<sys/types.h>
#include<sys/time.h>
#include<sys/resource/h>
#include<sys/wait.h>
pid_t wait3(int*status,int oprions,struct rusage*rusage)
成功返回进程ID
失败-1
#include<sys/types.h>
#include<sys/time.h>
#include<sys/resource/h>
#include<sys/wait.h>
pid_t wait4(pid_t pid,int *status,int options,struct rusage*rusage)
用户ID 组ID
#include<sys/types.h>
#include<unistd.h>
uid_t getuid(void)//实际用户标识符
gid_t getgid(void)//实际组标识符
uid_t gettuid(void)//有效用户标识符
gid_t getegid(void)//有效组标识符
成功0失败-1
#include<sys/tupes.h>
#include<unistd.h>
int setuid(uid_t uid)//超-实校设,普-效
int setgid(gid_t gid)//超-实校设,普-效
成功0失败-1
#include<sys/tupes.h>
#include<unistd.h>
int setreuid(uid_t ruid,uid_t euid)//实际有效用户交换
int setregid(gid_t rgid,gid_t egid)//实际有效组交换
成功0失败-1
#include<sys/tupes.h>
#include<unistd.h>
int seteuid(uid_t euid)
int setegif(gid_t egid)
system函数可用返回非零,不可用返回0
#include<stdlib.h>
int system(const char*smdstring)
system和exec都可以执行进程外的命令,system是在原进程上开辟了一个新的进程,但是exec是用新进程(命令)覆盖了原有的进程。system和exec都有能产生返回值,system的返回值并不影响原有进程,但是exec的返回值影响了原进程。
进程组
#include<sys/types.h>
#include<unistd.h>
pid_t getpgrp(void)//进程组ID=进程组长ID
#include<sys/types.h>
#include<unistd.h>
int setpgid(pid_t pid,pid_t pgid)
参加或设置进程的组ID;两参数一样,更为进程组长
出错
#include<errno.h>
errno Linux下宏定义常量。LinuxCAPI函数异常会赋整数值
会话期:多个进程组的集合,只有一个前台进程组
#include<sys/types.h>
#include<unistd.h>
pid_t setsid(void)//成功ID错误-1
建立对话期。
控制终端
#include<sys/types.h>
#include<unistd.h>
pid_t tcgetpgrp(int fd)
成功获得前台进程组ID,失败-1
fd:进程终端
#include<sys/types.h>
#include<unistd.h>
int tcsetpgrp(int fd,pid_t pgrpid)
置某一进程组为前台进程组,成功返回0,失败-1
fd:进程终端
信号
#include<signal.h>
abort()//调用函数产生夭折信号SIGABRT
alarm()//超过设置时间产生SIGALRM
kill -l 查看信号列表man 7 signal 查看详情
#include<setimp.h>
int setjmp(jmp_buf envbuf)
envbuf缓冲区,博阿村系统堆栈内容
#include<setimp.h>
void longjmp(imp_buf envbuf,int val)
val 来自setjmp返回值
信号处理函数
#include<signal.h>
void(*signal(int signum,void (*handler)(int)))(int)
//handler :SIG_IGN内核忽略此信号
//SIG_DFL系统默认动作
//指定函数:信号处理程序
注册某个特定信号的处理程序成功返回以前处理配置,出错SIG_ERR
不能处理SIGSTOP(单个信号注册函数)
POSIX定义
typedef void (*signhandler_t)(int)
signhandler_t signal(int signum,sighanler_t handler)
成功0失败-1
#include<signal.h>
int sigaction(int signum,const struct sigaction*act,struct sigaction*oldact)
注册函数(多个信号阻塞注册函数)
struct sigaction{
void(*sa_handler)(int);
老类型的信号处理函数
void(*sa_sigaction)(int,siginfo_t*,void);
新类型的信号处理函数
传入信号,信号相关信息,保留
sigset_t sa_mask;
将要被阻塞的信号集合
int sa_flags;
信号处理方式掩码
void(*sa_restorer)(void);
保留不使用
}
信号集
#include<signal.h>
int sigemptyset(sigset_t *set)
int sigfillset(sigset_t*set)
包含所有信号
int sigaddset(sigset_t*set,int signum)
成功0出错-1
int sigdelset(sigset_t *set,int signum)
真1假0
intsigismenber(const sigset_t*set,int signum)
是否包含signum信号
信号发送函数
#include<sys/types.h>
#include<signal.h>
int kill(pid_t pid,int signum)
成功0出错-1
pid>0信号发送给进程号pid进程
pid=0信号发送给同进程组的所有进程
pid<0&&pid!=-1进程组ID为pid绝对值的所有进程发送信号
pid=-1自己+进程ID>1的发送信号
成功0出错-1
#include<sys/types.h>
#include<signal.h>
int raise(int signum)
向进程自己发信号值
成功0出错-1
#include<signal.h>
#include<unistd.h>
int sigqueue(pid_t pid ,int signum,const union sigval val)
只能是一个进程发送信号
typedef union sigval{
int sival_int;
void *sival_ptr;
指向要传递的信号参数
}sigval_t;
#include<unistd.h>
unsigned int alarm(unsigned int seconds)
若进程已设闹钟返回上个剩余时间否则返回0
到时间调用SIFALRM的注册函数
时钟处理
成功0出错-1
#include<sys/time.h>
int setitimer(int which,const struct itimerval*value,struct itimerval*oldvalue)
which定时器类型
ITIMER_REAL真实计时器SIGALRM
ITIMER_VIRTUAL虚拟计时器、程序执行时间、去除系统调用+去除程序睡眠SIGVTALRM
ITIMER_PROF实用计时器、用户进程开始后计时、用户态+内核SIGPROF
value设置为计时器当前值。oldvalueNULL返回计时器原有值
int getitimer(int which,struct itimerval*value)
struct itimerval
{struct timeval it_interval;
计时器重启动间歇值
struct timerval it_value;};
计时器安装后首先启动初始值
struct timeval
{long tv_sec;
时间秒数部分
long tv_usec;};
时间微妙部分1/1000000
#include<stdlib.h>
void abort(void)
SIGABORT
信号阻塞
#include<signal.h>
int sigprocmask(int how,const sigset_t*set,sigset_t*oldset)
全程阻塞/屏蔽信号
how:
SIG_BLOCK 逻辑加
SIG_UNBLOCK逻辑减
SIG_SETMASK赋值
set信号集、当前信号掩码
#include<signal.h>
int sigsuspend(const sigset_t *sigmask)
进程挂起,等待放行信号
出错返回-1,errno设置为EINTR
睡眠函数
#include<unistd.h>
usigned int sleep(unsigned int seconds)//进程睡眠seconds秒
void usleep(unsigned long usec)//睡眠usec毫秒
int nanosleep(const struct timespec *rqtp, struct timespec *rmtp);//纳秒
内部由alarm()和pause()实现,最好不混用
进程间通信
管道(匿名管道)内存
shell中用
输出 | 接收
#include<unistd.h>
int pipe(int fd[2]) //成功0出错-1
fd[0]发送端fd[1]接收端 关闭用close();
fork()成功,子进程可继承管道
命名管道(FIFO)文件系统
shell中用
mkfifo [option] name…
#include<sys/types.h>
#include<sys/stat.h>
int mkfifo(const char*pathname,mode_t mode)//成功0出错-1
共享内存
shell中用
ipcs
#include<sys/shm.h>
struct shmid_ds{//不同系统不一样,系统手册
struct ipc_perm shm_perm;//对应ipc_perm结构
size_t shm_segsz;//区域字节数
pid_t shm_lpid;//最近一次调用shmop函数的ID
pid_t shm_cpid;//创建共享内存的进程ID
unsigned short shm_lkcnt;//被锁定时间数
unsigned long shm_nattch;//当期使用的进程数
time_t shm_atime;//最近一次附加操作时间
time_t shm_dtime;//最近一次分离操作时间
time_t shm_ctime;}//最近一次修改时间
创建打开共享内存
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/shm.h>
int shmget(key_t key,int size,int flag)//成功返回ID,出错-1
//key取值,flag
IPC_PRIVATE,flag无效,创建新共享内存;
不为IPC_PRIVATE,且flag设置IPC_CREAT位没有IPC_EXCL位,key为键值,打开共享内存;否则创建共享内存
不为IPC_PRIVATE,且flag设置IPC_CREAT位 | IPC_EXCL位,可以为键值,若已存在key键值,返回EEXIST错误;否则创建共享内存
附加(要使用附加地址空间)
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/shm.h>
void *shmat(int shmid,const void *addr,int flag)
//成功返回共享内存段指针且shm_nattcnt++,出错-1
shmid,NULL,读写方式 让内核决定第一个可以引入的位置
shmid,!0,SHMRND 引入addr所指位置(只对一种硬件上运行应用程序
分离(进程脱离共享内存,不删除共享内存
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/shm.h>
int shmdt(void*addr)
//成功返回0且shm_nattch--,失败-1.
addr为shmat的返回值
共享内存控制
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/shm.h>
int shmctl(int shmid,int cmd,struct shmid_ds *buf)
//成功0,失败-1
cmd
IPC_STAT buf=shmid_ds
IPC_SET 存shm_per.uid,shm_per.gid,shm_per.mode(进程id=shm_perm.cuid||进程id==shm_perm.uid)或者超级用户特权进程
IPC_RMID 当0==shmid_ds&&0==shm_nattch 执行删除共享内存段
SHM_LOCK 超级用户:锁定共享内存段在内存
SHM_UNLOCK 超级用户:解锁共享内存段
操纵函数
创建线程
pthread_self()可以获得当前线程的id
int pthread_attr_init (pthread_attr_t* attr);//对线程属性变量的初始化.成功: 0 失败: -1
int pthread_attr_setscope (pthread_attr_t* attr, int scope);//attr属性。成功0失败 -1
scope:PTHREAD_SCOPE_SYSTEM,表示与系统中所有线程一起竞争CPU时间,默认,Linux仅此项
PTHREAD_SCOPE_PROCESS,表示仅与同进程中的线程竞争CPU
int pthread_attr_setdetachstate (pthread_attr_t* attr, int detachstate);//attr属性。成功0失败 -1
detachstate:
PTHREAD_CREATE_JOINABLE,能用pthread_join()来同步,默认缺省状态
PTHREAD_CREATE_DETACHED,不能用pthread_join()来同步,且在退出时自行释放所占用的资源,这个属性也可以在线程创建并运行以后用pthread_detach()来设置,而一旦设置为PTHREAD_CREATE_DETACHED状态(不论是创建时设置还是运行时设置)则不能再恢复到PTHREAD_CREATE_JOINABLE状态。
int pthread_attr_setschedparam (pthread_attr_t* attr, struct sched_param* param);//线程优先级.
成功0失败 -1
param:线程优先级。一个struct sched_param结构,目前仅有一个sched_priority整型变量表示线程的运行优先级。这个参数仅当调度策略为实时(即SCHED_RR或SCHED_FIFO)时才有效,并可以在运行时通过pthread_setschedparam()函数来改变,缺省为0
int pthread_attr_getschedparam (pthread_attr_t* attr, struct sched_param* param);//成功0失败 -1
获取线程优先级。
attr:线程属性;
param:线程优先级;
int pthread_attr_destroy(pthread_attr_t *attr);//删除线程的属性
成功返回0
错误返回错误代码
#include <pthread.h>
int pthread_create(pthread_t *restrict thread,//线程ID
const pthread_attr_t *restrict attr,//线程的各种属性
void *(*start_routine)(void*), //start_routine线程函数起始地址
void *restrict arg);//start_routine的参数;成功返回0,失败返回错误号pthread_attr_t主要包括scope属性、detach属性、堆栈地址、堆栈大小、优先级
信号处理函数的控制流程只是在信号递达时产生,在处理完信号之后就结束,而多线程的控制流程可以长期并存,操作系统会在各线程之间调度和切换,就像在多个进程之间调度和切换一样
int pthread_kill(pthread_t thread, int sig);//向某个线程传递信号.thread要有signal处理函数
pthread_t thread:线程号
int sig:信号
int pthread_cancel(pthread_t thread)
发送终止信号给thread线程,如果成功则返回0,否则为非0值。发送成功并不意味着thread会终止
void pthread_exit(void *value_ptr)//终止当前线程
int pthread_join(pthread_t thread, void **value_ptr);//线程挂起直到thread线程终止;成功返回0,失败返回错误号
int pthread_detach(pthread_t thread);//成功返回0,失败返回错误号
主线程并不希望因为调用pthread_join而阻塞(因为还要继续处理之后到来的),这时可以在子线程中加入代码
pthread_detach(pthread_self())
或者父线程调用
pthread_detach(thread_id)(
互斥锁
#include <pthread.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;//宏,静态初始化
int pthread_mutex_init(pthread_mutex_t *restrict mutex,
const pthread_mutexattr_t *restrict attr);//动态初始化,成功返回0,失败返回错误号
PTHREAD_MUTEX_TIMED_NP,默认缺省值(NULL),也就是普通锁。当一个线程加锁以后,其余请求锁的线程将形成一个等待队列,并在解锁后按优先级获得锁。这种锁策略保证了资源分配的公平性。
PTHREAD_MUTEX_RECURSIVE_NP,嵌套锁,允许同一个线程对同一个锁成功获得多次,并通过多次unlock解锁。如果是不同线程请求,则在加锁线程解锁时重新竞争。
PTHREAD_MUTEX_ERRORCHECK_NP,检错锁,如果同一个线程请求同一个锁,则返回EDEADLK,否则与普通锁类型动作相同。这样就保证当不允许多次加锁时不会出现最简单情况下的死锁。
PTHREAD_MUTEX_ADAPTIVE_NP,适应锁,动作最简单的锁类型,仅等待解锁后重新竞争
int pthread_mutex_destroy(pthread_mutex_t *mutex);//释放它所占用的资源,在Linux互斥锁并不占用任何资源,除了检查锁状态以外(锁定状态则返回EBUSY)没有其他动作
锁操作
int pthread_mutex_lock(pthread_mutex_t *mutex)//加锁
int pthread_mutex_unlock(pthread_mutex_t *mutex)//解锁
int pthread_mutex_trylock(pthread_mutex_t *mutex)//测试加锁
通用套接口地址数据结构
#include<sys/socket.h>
struct sockaddr{
unit8_t sa_len;
sa_family_t sa_family;//协议族 AF_XXX
char sa_data[14];};//14字节协议地址
IPV4套接接口地址数据结构
<netinet/in.h>
struct sockaddr_in{
unit8_t sin_len;//不用设置
sa_family_t sin_family;//协议族 AF_INET
in_port_t sin_port;//16位TCP或UDP端口号,网络字节序 (大端模式)
struct in_addr sin_addr;//32位IPv4,网络字节序
struct in_addr{
unsigned char sin_zero[8];};//未用0
in_addr_t s_addr;};
字节排序函数
#include <arpa/inet.h>
uint32_t htonl(uint32_t hostlong);本地long转网络long
uint16_t htons(uint16_t hostshort);返回网络字节序
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);返回主机字节序
h-host n-newwork s-short l-long
字节操纵函数
#include<string.h>
void bzero(void*dest,size_t nbytes)//将地址dest开始nbytes置0
void bcopy(const void *ptr1,const void *ptr2,size_t nbytes)//复制内存数据
int bcmp(const void*ptr1,const void*ptr2,size_t nbytes)//比较内存数据大小
void memset(void *dest,int c,size_t len)//把dest中len设置为c
void memcpy(void *dest,const void*src,size_t nbytes);//复制内存数据
int memcmp(const void*ptr1,const void *ptr2,size_t nbytes)//比较内存数据大小
IP地址转换函数
#include <arpa/inet.h>
int inet_aton(const char *strptr, struct in_addr *addrptr);成功1失败0,结果在addrptr
in_addr_t inet_addr(const char *strptr);//成功返回32位二进制网络字节序地址,出错INADDR_NONE
int inet_pton(int family, const char *strptr, void *addrptr);//字符串-》in_addr
char *inet_ntoa(struct in_addr inaddr);//成功返回十进制数串指针,失败NULL
const char *inet_ntop(int family, const void *addrptr, char *strptr, size_t len);//in_addr-》字符串
IP和域名转换
#include<netdb.h>
struct hostent *gethostbyname(const char*hostname)域名-》IP地址
struct hostent*gethostbyaddr(const char*addr,size_t len,int family)IP地址-》域名;ipv4 的len4;IPv6len16
若失败返回NULL,并设全局变量h_errno;h_streeror获取详细出错信息
HOST_NOT_FOUND找不到主机
TRY_AGAIN出错重试
NO_RECOVERY不可修复性错误
NO_DATA指定的名字有效但没有定义
struct hostent{
char*h_name;//主机正式名称
char*h_aliases;//主机别名
int h_addrtype;//IPV4为 AF_INET
int h_length;//Ipv4为4字节
char**h_addr_list;};//IP地址列表
#define h_addr h_addr_list[0]//主机第一个IP地址
创建套接口socket
#include<sys/types.h>
#include<sys/socket.h>
int socket(int family,int type,int potocol);//成功返回套接口描述符,失败-1
不能用open()访问sockfs文件
fimaly:
PF_UNIX
UNIX协议族
PF_INET ipv4 AF_INET
PF_INET6 ipv6 AF_INET6
AF_ROUTE 路由套接口
type
SOCK_STREAM TCP方式 ptotoco=0
SOCK_DGRAM UDP方式 ptotoco=0
SOCK_RAW 原始套接口
SOCK_PACKET 支持数据链路访问ptotoco=0
绑定端口
int bind(int sockfd, const struct sockaddr *myaddr, socklen_t addrlen);//成功0失败-1
//描述符 结构体指针 结构体长度=sizeof( struct sockaddr)
error捕捉错误
EBADF描述符sockfd不是合法的socket
EACCESS权限不足
ENOTSOCK是文件描述符,但不是socket
等待监听函数
int listen(int sockfd, int backlog);//成功0,失败-1
blocklog支持最大连接请求数,超过客户端收到ECONNREFUSED
适用SOCK_STREAM tcp ipv4醉倒128个客户端
SOCK_SEQPACKET非网络协议X.25或广播协议AX.25
error捕捉错误
EBADF描述符对象不是合法的socket
EACCESS权限不足
EOPNOTSUPP此socket不支持listen模式
接受连接函数
#include<sys/types.h>
#include<sys/socket.h>
int accept(int sockfd,struct sockaddr*addr,socketlen_t*addrlen)
//成功返回新的套接口描述符,出错-1
int addr_len=sizeof(struct sockaddr_in)
addrlen=&addr_len
error捕捉错误
EBADF描述符对象不是合法的socket
EFAULT参数addr指针指向无法读取的内存空间
ENOTSOCK是文件描述符,但不是socket
EOPNOTSUPP指定socket不是SOCK_STREAM
EPERM防火墙拒绝这个连接
ENOBUFS系统缓冲内存不足
ENOMEM核心内存不足
请求链接函数
//客户段-》服务器
#include<sys/types.h>
#include<sys/socket.h>
int connect(int sockfd,const struct sockaddr*serv_addr,int addrlen)
//连接成功0,失败-1
error捕捉错误
EBADF描述符对象不是合法的socket
EFAULT参数addr指针指向无法读取的内存空间
ENOTSOCK是文件描述符,但不是socket
EISCONN sockfd的socket已经处于连接状态
ECONNREFUED连接要求被服务器拒绝
ETIMEOUT连接超时
ENETUNREACH无法传送数据包至指定主机
EAFNOSUPPORTsockaddr结构和sa_family不正确
EALREADY socket不能阻断,以前连接操作还未完成
数据发送函数
#include<sys/types.h>
#include<sys/socket.h>
int send(int sockfd,const void*msg,int len,unsigned int flags)
//成功但会发送字符数,失败-1
flags一般0;其他
MSG_OOB传送数据以带外out-of-band 的方式送出
MSG_DONTROUTE取消路由表查询
MSG_WAITALL设置数据传送为不可阻断的传输,除非有错误或信号产生
MSG_NOSIGNAL此传输不可被SIGPIPE信号中断
error捕捉错误
EBADF描述符sockfd不是合法的socket
EFAULT参数addr指针指向无法读取的内存空间
ENOTSOCK是文件描述符,但不是socket
EINTR发送进程被信号中断
EAGAIN操作中断进程,但socket不允许被中断
ENOBUFS系统缓冲内存不足
ENOMEM核心内存不足
EINVAL传给系统调用的参数不正确
数据接受函数
#include<sys/types.h>
#include<sys/socket.h>
int recv(int sockfd,void *buf,int len usigned int flags)
//成功但会发送字符数,失败-1
flags一般0;其他
MSG_OOB接收以带外out-of-band 送出的数据
MSG_PEEK返回来的数据并不会在系统内删除,若再调用recv时会返回相同数据内容
MSG_WAITALL强迫接收到len大小的数据后才返回,除非有错误或信号产生
MSG_NOSIGNAL此传输不可被SIGPIPE信号中断
error捕捉错误
EBADF描述符sockfd不是合法的socket
EFAULT参数addr指针指向无法读取的内存空间
ENOTSOCK是文件描述符,但不是socket
EINTR进程被信号中断
EAGAIN动作阻断进程,但socket不允许被阻断
ENOBUFS系统缓冲内存不足
ENOMEM核心内存不足
EINVAL参数不正确
文件读写
#include<unistd.h>
ssize_t read(int sockfd,void *buf,size_t count)//出错-1,否则返回读入的字节数
fd文件描述符;buf指针缓冲区;count要读取的字节数
#include<unistd.h>
ssize_t write(int sockfd,void *buf,size_t count)//出错-1,否则返回成功发送的字节数
fd文件描述符;buf指针缓冲区;count要写入取的字节数
关闭socket
close(socketId);
typedef struct
{
/* XPG4.2 requires this member name. Otherwise avoid the name
from the global namespace. */
#ifdef __USE_XOPEN
__fd_mask fds_bits[__FD_SETSIZE / __NFDBITS];
# define __FDS_BITS(set) ((set)->fds_bits)
#else
__fd_mask __fds_bits[__FD_SETSIZE / __NFDBITS];
# define __FDS_BITS(set) ((set)->__fds_bits)
#endif
} fd_set;
fd_set类四个宏来操作:
FD_ZERO(fd_set *fdset);将指定的文件描述符集清空,在对文件描述符集合进行设置前,必须对其进行初始化,如果不清空,由于在系统分配内存空间后,通常并不作清空处理,所以结果是不可知的。
FD_SET(fd_set *fdset);用于在文件描述符集合中增加一个新的文件描述符。
FD_CLR(fd_set *fdset);用于在文件描述符集合中删除一个文件描述符。
FD_ISSET(int fd,fd_set *fdset);用于测试指定的文件描述符是否在该集合中
#include <sys/time.h>
#include <unistd.h>
int select(int nfds, fd_set *readset, fd_set *writeset,fd_set* exceptset, struct tim *timeout);//测试指定的fd待处理?可读/可写/有异常条件
nfds:需要检查的文件描述字个数(即检查到fd_set的第几位),数值应该比三组fd_set中所含的最大fd值更大,一般设为三组fd_set中所含的最大fd值加1(如在readset,writeset,exceptset中所含最大的fd为5,则nfds=6,因为fd是从0开始的)。设这个值是为提高效率,使函数不必检查fd_set的所有1024位。
readset: 待检可读性的文件描述字组。
writeset:待检可写性的文件描述字组。
exceptset:待检是否有异常条件出现的文件描述字组。(注:错误不包括在异常条件之内)
timeout:用于描述一段时间长度,如果在这个时间内,需要监视的描述符没有事件发生则函数返回,返回值为0。
有三种可能:
1.timeout=NULL(阻塞:select将一直被阻塞,直到某个文件描述符上发生了事件)
2.timeout所指向的结构设为非零时间(等待固定时间:如果在指定的时间段里有事件发生或者时间耗尽,函数均返回)
3.timeout所指向的结构,时间设为0(非阻塞:仅检测描述符集合的状态,然后立即返回,并不等待外部事件的发生)
返回值:
返回对应位仍然为1的fd的总数。
Remarks:
三组fd_set均将某些fd位置0,只有那些可读,可写以及有异常条件待处理的fd位仍然为1。
举个例子,比如recv(), 在没有数据到来调用它的时候,你的线程将被阻塞,如果数据一直不来,你的线程就要阻塞很久.这样显然不好. 所以采用select来查看套节字是否可读(也就是是否有数据读了)
fd的最大值必须<FD_SETSIZE
select函数用于在非阻塞中,当一个套接字或一组套接字有信号时通知你,系统提供select函数来实现多路复用输入/输出模型
- Linux下进程控制函数
- Linux进程控制函数
- linux 进程控制函数
- Linux 进程控制函数
- Linux下进程控制
- Linux-进程控制中的函数
- Linux下的进程控制
- Linux下进程控制实验
- linux下的进程控制
- Linux进程控制-fork函数-进程控制执行
- Linux笔记 7 --- 进程控制函数
- linux进程控制exec 函数族
- linux 进程控制编程 exec族函数
- 【Linux】进程控制—exec函数族
- Linux下进程管理与控制
- Linux环境下的进程控制
- linux下的进程控制编程
- Linux系统下的进程控制
- JavaScript判断回文字符串
- 电话验证码通道
- 单例模式(二)
- 使用eclipse在大量项目中查找指定文件
- 交易引擎的对账状态为空的处理方式
- Linux下进程控制函数
- 由89C2051设计的电子钟
- 排序-java实现的选择/插入/希尔排序
- jquery文本框改变事件
- 网络变压器在以太网中的作用
- ZZULIOJ 1913: 小火山的计算能力(栈模拟)
- 系统标签控制器的使用——UITabBarController
- Bad Request(Invalid Hostname)错误分析
- 金融行业的BI应用分析