LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 1588|回复: 7

如何访问其他进程的 socket 句柄?

[复制链接]
发表于 2005-12-15 13:04:15 | 显示全部楼层 |阅读模式
我想访问某个特定进程的socket句柄?包括读、写、关闭等。在windows下我们可以通过HOOK或者远程线程在其他进程内启动一个线程,进而安全地使用他的文件资源,但 Linux 下是否有类似的机制?我知道通过 kernel_thread 可以启动一个共享的内核线程,可是这个线程不具有固定的进程上下文,如果用死循环判断会阻塞系统,所以不太合适,最好的办法就是启动一个用户态线程,有方法否?或者另一个办法就是共享目标进程的进程上下文,从而在我的进程里直接使用目标进程的文件句柄,能做到吗?

我试过通过复制目标进程的任务结构到当前进程,确实可以关闭目标进程的socket,但目标进程在访问socket句柄时会出错,报告句柄无效,我想可能是因为任务结构是用 memcpy 复制的,所以对资源的访问上可能有些不安全的地方。实际上我希望目标进程在访问被关闭的 socket 后象正常的断线一样的返回 0 或 -1,不知道除了远程线程外还有什么好的办法。
发表于 2005-12-19 12:48:52 | 显示全部楼层
Post by meee
我知道通过 kernel_thread 可以启动一个共享的内核线程,可是这个线程不具有固定的进程上下文

什么叫"固定的进程上下文"? 你所说的"共享"又是什么意思?

我试过通过复制目标进程的任务结构到当前进程,确实可以关闭目标进程的socket,但目标进程在访问socket句柄时会出错,报告句柄无效

你都关闭了,再访问自然会出错
回复 支持 反对

使用道具 举报

发表于 2005-12-19 13:25:24 | 显示全部楼层
文件句柄隶属于进程,不同进程之间不可以简单的传送文件句柄吧?

但对于socket,可以通过创建socket文件来做到通信.
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-12-23 15:16:59 | 显示全部楼层
Post by pointer
文件句柄隶属于进程,不同进程之间不可以简单的传送文件句柄吧?


可是我通过复制任务环境确实可以关闭文件。这也是我纳闷的地方。但我想即便可以访问,也一定还有其他要注意的地方,否则怎么会出错呢?

Post by pointer
但对于socket,可以通过创建socket文件来做到通信.


我不是要和某个SOCKET通讯,SOCKET通讯这么简单的问题没必要发贴来问了,我要从自己的进程中控制其他进程的SOCKET,包括关闭它。你明白吗?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-12-23 15:22:10 | 显示全部楼层
Post by rickxbx
什么叫"固定的进程上下文"? 你所说的"共享"又是什么意思?


可能是我没有表达清楚。内核的进程上下文就是随调用他的进程的上下文,在多任务环境中,内核被多个进程共享,它的进程上下文在不同的进程访问的时候当然是不一样的,所以我说不是固定的。

Post by rickxbx
你都关闭了,再访问自然会出错


实际上如果我们在同一个进程中,如果你试图读取一个已经关闭的SOCKET的时候会简单地返回 0 或 -1,而不是报告文件句柄无效。
回复 支持 反对

使用道具 举报

发表于 2005-12-23 22:52:17 | 显示全部楼层
You can send the fd between processes over a unix-socket.
please check <<UNIX® Network Programming>> for detail.
回复 支持 反对

使用道具 举报

 楼主| 发表于 2006-1-1 12:16:29 | 显示全部楼层
Post by daemeon
You can send the fd between processes over a unix-socket.
please check <<UNIX® Network Programming>> for detail.


I think you mean to create a socket with "F_UNIX" parameter, as I haven't the book, could you kindly introduce the theory a little more detailed?
回复 支持 反对

使用道具 举报

发表于 2006-1-1 14:07:58 | 显示全部楼层
Recv file descriptor.

  1. #include <sys/types.h>
  2. #include <sys/socket.h>
  3. #include <sys/un.h>
  4. #include <string.h>
  5. #include <stdio.h>
  6. #include <stdlib.h>

  7. ssize_t recv_fd(int fd, void *ptr, size_t nbytes, int *recvfd)
  8. {
  9.         struct msghdr msg;
  10.         struct iovec iov[1];
  11.         ssize_t n;

  12.         union {
  13.                 struct cmsghdr cm;
  14.                 char     control[CMSG_SPACE(sizeof (int))];
  15.         } control_un;
  16.         struct cmsghdr  *cmptr;
  17.         msg.msg_control  = control_un.control;
  18.         msg.msg_controllen = sizeof(control_un.control);

  19.         msg.msg_name = NULL;
  20.         msg.msg_namelen = 0;
  21.         iov[0].iov_base = ptr;
  22.         iov[0].iov_len = nbytes;
  23.         msg.msg_iov = iov;
  24.         msg.msg_iovlen = 1;
  25.         if ((n = recvmsg(fd, &msg, 0)) <= 0)
  26.                 return -1;

  27.         if ((cmptr = CMSG_FIRSTHDR(&msg)) != NULL &&
  28.                         cmptr->cmsg_len == CMSG_LEN(sizeof(int))) {
  29.                 if (cmptr->cmsg_level != SOL_SOCKET)  
  30.                         return -1;
  31.                 if (cmptr->cmsg_type != SCM_RIGHTS)
  32.                         return -1;
  33.                 *recvfd = *((int *) CMSG_DATA(cmptr));
  34.         } else {
  35.                 *recvfd = -1;
  36.         }
  37.         return (n);
  38. }

  39. int main(int argc, char *argv[]) {
  40.         char c;
  41.         int fd, newfd;
  42.         struct sockaddr_un addr;

  43.         fd = socket(PF_UNIX, SOCK_STREAM, 0);
  44.         bzero(&addr, sizeof(addr));
  45.         addr.sun_family = PF_UNIX;
  46.         strcpy(addr.sun_path, "/tmp/fd.socket");

  47.         unlink("/tmp/fd.socket");
  48.         bind(fd, (struct sockaddr *)&addr, sizeof(addr));

  49.         listen(fd, 10);
  50.         while((newfd = accept(fd, NULL, 0)) >= 0) {
  51.                 int recvfd;
  52.                 recv_fd(newfd, &c, 1, &recvfd);
  53.                 close(newfd);
  54.                 /* Now, we get the file descriptor. */
  55.         }
  56. }
复制代码


Send file descriptor.

  1. #include <sys/types.h>
  2. #include <sys/socket.h>
  3. #include <sys/stat.h>
  4. #include <sys/un.h>
  5. #include <fcntl.h>
  6. #include <string.h>
  7. #include <stdio.h>
  8. #include <stdlib.h>

  9. ssize_t send_fd(int fd, void *ptr, size_t nbytes, int sendfd)
  10. {
  11.         struct msghdr msg;
  12.         struct iovec iov[1];

  13.         union {
  14.                 struct cmsghdr cm;
  15.                 char    control[CMSG_SPACE(sizeof(int))];
  16.         } control_un;
  17.         struct cmsghdr *cmptr;
  18.         msg.msg_control = control_un.control;
  19.         msg.msg_controllen = sizeof(control_un.control);
  20.         cmptr = CMSG_FIRSTHDR(&msg);
  21.         cmptr->cmsg_len = CMSG_LEN(sizeof(int));
  22.         cmptr->cmsg_level = SOL_SOCKET;
  23.         cmptr->cmsg_type = SCM_RIGHTS;
  24.         *((int *) CMSG_DATA(cmptr)) = sendfd;

  25.         msg.msg_name = NULL;
  26.         msg.msg_namelen = 0;
  27.         iov[0].iov_base = ptr;
  28.         iov[0].iov_len = nbytes;
  29.         msg.msg_iov = iov;
  30.         msg.msg_iovlen = 1;
  31.         return (sendmsg(fd, &msg, 0));
  32. }

  33. int main(int argc, char *argv[]) {
  34.         int fd, sendfd;
  35.         struct sockaddr_un addr;
  36.         fd = socket (PF_UNIX, SOCK_STREAM, 0);
  37.         bzero(&addr, sizeof(addr));
  38.         addr.sun_family = PF_UNIX;
  39.         strcpy(addr.sun_path, "/tmp/fd.socket");

  40.         connect(fd, (struct sockaddr *)&addr, sizeof(addr));

  41.         sendfd = open("/etc/inittab", O_RDONLY);
  42.         /* send a file descriptor. */
  43.         send_fd(fd, "", 1, sendfd);       
  44.         return 0;
  45. }
复制代码
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表