xiaoshimimi 发表于 2005-7-6 22:25:16

这是socket.c中的sys_sendto()函数代码.

/*
*        Send a datagram to a given address. We move the address into kernel(将一个数据包送到给定的地址)
*        space and check the user space data area is readable before invoking(我们移动这个地址到内核空间)
*        the protocol.(并在调用协议前检查用户空间的数据与是否可读.)
*/

asmlinkage long sys_sendto(int fd, void * buff, size_t len, unsigned flags,
                           struct sockaddr *addr, int addr_len)
/*无连接模式的套接字一经建立(并且绑定到一个套接字地址)以后就可以
*进行通信,而无需先建立连接.此时,每个报文都要提供对方的地址.
*所以,sento()用于程序界面为:int sendto(int s, const void *msg, size_t len, int flags, const struct sockaddr *to, socklen_t tolen);
*参数to 指向对方的地址即:sockaddr数据结构.而tolen则为地址的长度.这个函数是专为
*"无连接"模式设计的.若工作在"有连接"模式则应将参数to 设置成NULL,而将tolen设置成0.*/
{
        struct socket *sock;                                //套接字结构体
        char address;        //地址
        int err;
        struct msghdr msg;                                //报文结构体.每个msghdr数据结构代表着一个报文.
        struct iovec iov;                                        //一块数据.
        //struct数据结构声明:(在include\linux\uio.h中)
        //struct iovec
        //{
        //        void *iov_base;                /* BSD uses caddr_t (1003.1g requires void *) */
        //        __kernel_size_t iov_len; /* Must be size_t (1003.1g) */
        //};
        sock = sockfd_lookup(fd, &err);                //根据文件描述符得到相应的套接字.
        if (!sock)                                                        //如果失败则跳转到相应的处理程序段.
                goto out;
        iov.iov_base=buff;                                        //将要传递的报文信息附给iov数据块.该数
        iov.iov_len=len;                                                //据块成为要发送的报文的代表.
        msg.msg_name=NULL;                                        //为报文附值.(名字暂时为空,得到地址后再为它附值)
        msg.msg_iov=&iov;                                        //数据块被封装到报文中.
        msg.msg_iovlen=1;                                        //报文的数据块长度为1.
        msg.msg_control=NULL;                                //控制字段为空,只是发送而已没有其他控制信息.
        msg.msg_controllen=0;
        msg.msg_namelen=0;
        if(addr)
        {
                err = move_addr_to_kernel(addr, addr_len, address);        //将地址移到内核空间.
                if (err < 0)                                                                                        //如果失败则跳到相关的处理段.
                        goto out_put;
                msg.msg_name=address;                                                                //成功则为名字字段附值.
                msg.msg_namelen=addr_len;
        }
        if (sock->file->f_flags & O_NONBLOCK)                                                //对于标志位flag的处理?????????????????
                flags |= MSG_DONTWAIT;
        msg.msg_flags = flags;
        err = sock_sendmsg(sock, &msg, len);                                //通过套接字发送报文.

out_put:                                                        //将地址移到内核空间失败,先将sock输出再返回错误码.
        sockfd_put(sock);
out:                                                                        //根据文件描述符得到相应的套接字失败,直接返回错误码.
        return err;
}

标着一串问号的地方,是我不明白的地方,这个flag究竟起着怎样的作用,它和那些与他做运算的常数之间是什么关系?

多谢!!

_z_ 发表于 2005-7-7 11:35:25

判断socket是否阻塞

xiaoshimimi 发表于 2005-7-7 16:26:31

多谢:)

yuyulvxian 发表于 2005-9-27 10:55:26

为什么要将地址addr移入系统空间而不直接使用addr
系统应该可以直接使用用户态的地址啊 而且两者的虚拟地址是一样的
页: [1]
查看完整版本: 这是socket.c中的sys_sendto()函数代码.