fcntl:
ioctl函数提供对连接到fd的设备驱动程序的属性和操作的访问
extern int ioctl(int fd,unsigned long int request[,char * arg ....])
arg 是参数 可选的
因为有些属性需要使用返回值 这时不一定是0了
void prinft_screen_dimension(int fd)
{
int fd; //
struct winsize buf;
if (ioctl( fd, TIOCGWINZ,&buf ) != -1){
printf("%d rows x %d cols\n",buf.ws_row,buf.ws_col);
printf("%d wide x %d tall\n",buf.ws_xpixel,buf.ws_ypixel);
}
}
但是在数据比较重要的时候担心意外事故导致缓冲数据丢失
这时我们可以设置数据存入是同步的(即关闭缓冲属性)
描述符的属性被编码到一个整数中了
fcntl通过读写该整数位来设置文件描述符的属性。
使用fcntl取得此值 修改后 再用fcntl写回
#include <fcntl.h>
fcntl 原型为
extern int fcntl(int fd, int _cmd,... )
调用形式有
fcntl(int fd,int cmd);
fcntl(int fd,int cmd,long arg)
fcntl(int fd,int cmd,struct flock *lock)
fd 值相应的描述符,cmd 是指相应的操作
相应操作可以查看man fcntl 会发现fcntl不只会干这些哟。
这里我们用fcntl进行演示(关闭fd的缓冲属性 注意只有块设备与实际文件有这个属性)
int fd,va;
va = fcntl( fd,F_GETFD);
va | = O_SYNC;
fcntl( fd,F_SETFD,va);
当然也可以直接在open的同时进行设置。
不过open的属性设置没有用fcntl那样灵活。
#include<unistd.h>
int ioctl( int fd, int request, .../* void *arg */ ); 返回0——成功, -1——出错
第一个参数 fd 指示某个文件描述符(当然也包括 套接口描述符)
第二个参数 request 指示要ioctl执行的操作
第三个参数 总是某种指针,具体的指向类型依赖于 request 参数
我们可以把和网络相关的请求(request)划分为6 类:
套接口操作
文件操作
接口操作
ARP 高速缓存操作
路由表操作
流系统
下表列出了网络相关ioctl 请求的request 参数以及arg 地址必须指向的数据类型:
类别 request 说明 (第三个参数)数据类型
SIOCATMARK 是否位于带外标记 int
套接口 SIOCSPGRP 设置套接口的进程ID或组ID int
SIOCGPGRP 获取套接口的进程ID或组ID int
文件 FIONBIO 设置/清除非阻塞IO标识 int
FIOASYNC 设置/清除信号驱动异步IO标识 int
FIONREAD 获取接收缓冲区中的字节数 int
……
SIOCGIFCONF 获取所有接口的清单 struct ifconf
接口 SIOCSIFADDR 设置接口的ip地址 struct ifreq
SIOCGIFADDR 获取接口地址 struct ifreq
SIOCSIFFLAGS 设置接口标识 struct ifreq
SIOCGIFFLAGS 获取接口标识 struct ifreq
SIOCSIFDSTADDR 设置点到点地址 struct ifreq
SIOCGIFDSTADDR 获取点到点地址 struct ifreq
SICSIFBRDADDR 设置广播地址 struct ifreq
SICGIFBRDADDR 获取广播地址 struct ifreq
……
SIOCSARP 创建/修改ARP表项 struct arpreq
ARP SIOCGARP 获取ARP表项 struct arpreq
SIOCDARP 删除ARP表项 struct arpreq
路由 ……
(有很多request请求没有列出,而且不同的系统所提供的request也有所不同,比如linux就不提供SIOCGSIZIFCONF请求)
上面的表中,用ioctl执行接口操作的请求时,要用到结构体 struct ifconf 与 struct ifreq
struct ifconf{
int ifc_len; // 缓冲区ifcu_buf的大小
union{
caddr_t ifcu_buf; // 其实就是char *类型。
struct ifreq *ifcu_req; // 为ifconf分配空间时我们用ifcu_buf指针;当要取得或设置该缓冲区中的ifreq类型时,则用这个指针
}ifc_ifcu;
};
#define ifc_buf ifc_ifcu.ifcu_buf //buffer address
#define ifc_req ifc_ifcu.ifcu_req //array of structures returned
struct ifreq
{
char ifrn_name[IFNAMSIZ]; /* if name, e.g. "eth0" */
union {
struct sockaddr ifru_addr;
struct sockaddr ifru_dstaddr;
struct sockaddr ifru_broadaddr;
struct sockaddr ifru_netmask;
struct sockaddr ifru_hwaddr;
short ifru_flags;
int ifru_ivalue;
int ifru_mtu;
struct ifmap ifru_map;
char ifru_slave[IFNAMSIZ]; /* Just fits the size */
char ifru_newname[IFNAMSIZ];
void * ifru_data;
struct if_settings ifru_settings;
} ifr_ifru;
};
#define ifr_name ifr_ifrn.ifrn_name /* interface name */
#define ifr_hwaddr ifr_ifru.ifru_hwaddr /* MAC address */
#define ifr_addr ifr_ifru.ifru_addr /* address */
#define ifr_dstaddr ifr_ifru.ifru_dstaddr /* other end of p-p lnk */
#define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */
#define ifr_netmask ifr_ifru.ifru_netmask /* interface net mask */
#define ifr_flags ifr_ifru.ifru_flags /* flags */
#define ifr_metric ifr_ifru.ifru_ivalue /* metric */
#define ifr_mtu ifr_ifr