当前位置:   article > 正文

Linux下进程控制函数_请使用linux进程控制函数实现进程的阻塞

请使用linux进程控制函数实现进程的阻塞

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_RRSCHED_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函数来实现多路复用输入/输出模型

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/483171
推荐阅读
相关标签
  

闽ICP备14008679号