免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3253 | 回复: 4
打印 上一主题 下一主题

[C] 我的splice程序在Ubuntu正常,在CentOS就出错。各位大哥帮我看看 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-06-11 14:29 |只看该作者 |倒序浏览
  1. #ifndef SPLICE_H
  2. #define SPLICE_H

  3. #include <errno.h>
  4. #include <sys/uio.h>
  5. #include <sys/stat.h>
  6. #include <linux/unistd.h>

  7. #if defined(__i386__)
  8. #define __NR_sys_splice                313
  9. #define __NR_sys_tee                315
  10. #define __NR_sys_vmsplice        316
  11. #elif defined(__x86_64__)
  12. #define __NR_sys_splice                275
  13. #define __NR_sys_tee                276
  14. #define __NR_sys_vmsplice        278
  15. #elif defined(__powerpc__) || defined(__powerpc64__)
  16. #define __NR_sys_splice                283
  17. #define __NR_sys_tee                284
  18. #define __NR_sys_vmsplice        285
  19. #elif defined(__ia64__)
  20. #define __NR_sys_splice                1297
  21. #define __NR_sys_tee                1301
  22. #define __NR_sys_vmsplice        1302
  23. #else
  24. #error unsupported arch
  25. #endif

  26. #ifndef SPLICE_F_MOVE

  27. #define SPLICE_F_MOVE        (0x01)        /* move pages instead of copying */
  28. #define SPLICE_F_NONBLOCK (0x02) /* don't block on the pipe splicing (but */
  29.                                  /* we may still block on the fd we splice */
  30.                                  /* from/to, of course */
  31. #define SPLICE_F_MORE        (0x04)        /* expect more data */
  32. #define SPLICE_F_GIFT   (0x08)  /* pages passed in are a gift */

  33. #endif /* SPLICE_F_MOVE defined */

  34. /*
  35. * SPLICE_F_UNMAP was introduced later, so check for that seperately
  36. */
  37. #ifndef SPLICE_F_UNMAP
  38. #define SPLICE_F_UNMAP        (0x10)        /* undo vmsplice map */
  39. #endif

  40. static inline int ssplice(int fdin, loff_t *off_in, int fdout, loff_t *off_out,
  41.                           size_t len, unsigned int flags)
  42. {
  43.        
  44.         return syscall(__NR_sys_splice, fdin, off_in, fdout, off_out, len, flags);
  45. }

  46. static inline int stee(int fdin, int fdout, size_t len, unsigned int flags)
  47. {
  48.         return syscall(__NR_sys_tee, fdin, fdout, len, flags);
  49. }

  50. static inline int svmsplice(int fd, const struct iovec *iov,
  51.                             unsigned long nr_segs, unsigned int flags)
  52. {
  53.         return syscall(__NR_sys_vmsplice, fd, iov, nr_segs, flags);
  54. }

  55. #define SPLICE_SIZE        (64*1024)

  56. #define BUG_ON(c) assert(!(c))

  57. #define min(x,y) ({ \
  58.         typeof(x) _x = (x);     \
  59.         typeof(y) _y = (y);     \
  60.         (void) (&_x == &_y);            \
  61.         _x < _y ? _x : _y; })

  62. #define max(x,y) ({ \
  63.         typeof(x) _x = (x);     \
  64.         typeof(y) _y = (y);     \
  65.         (void) (&_x == &_y);            \
  66.         _x > _y ? _x : _y; })

  67. static inline int error(const char *n)
  68. {
  69.         perror(n);
  70.         return -1;
  71. }

  72. static int __check_pipe(int pfd)
  73. {
  74.         struct stat sb;

  75.         if (fstat(pfd, &sb) < 0)
  76.                 return error("stat");
  77.         if (!S_ISFIFO(sb.st_mode))
  78.                 return 1;

  79.         return 0;
  80. }

  81. static inline int check_input_pipe(void)
  82. {
  83.         if (!__check_pipe(STDIN_FILENO))
  84.                 return 0;

  85.         fprintf(stderr, "stdin must be a pipe\n");
  86.         return 1;
  87. }

  88. static inline int check_output_pipe(void)
  89. {
  90.         if (!__check_pipe(STDOUT_FILENO))
  91.                 return 0;

  92.         fprintf(stderr, "stdout must be a pipe\n");
  93.         return 1;
  94. }

  95. #endif
复制代码
  1. #include <time.h>
  2. #include <stdio.h>
  3. #include <errno.h>
  4. #include <fcntl.h>
  5. #include <netdb.h>
  6. #include <stdint.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <unistd.h>
  10. #include <sys/stat.h>
  11. #include <sys/time.h>
  12. #include <sys/epoll.h>
  13. #include <sys/types.h>
  14. #include <arpa/inet.h>
  15. #include <sys/ioctl.h>
  16. #include <sys/select.h>
  17. #include <sys/socket.h>
  18. #include <netinet/in.h>
  19. #include <netinet/ip.h>
  20. #include <netinet/tcp.h>
  21. #include <sys/resource.h>


  22. #include "splice.h"


  23. #define DestPort 80

  24. int pipefd[2];

  25. // Support for non-blocking I/O
  26. static int set_nonblocking(const int sockfd)
  27. {
  28.         int flags = 1;

  29.         if (ioctl(sockfd, FIONBIO, &flags) && ((flags = fcntl(sockfd, F_GETFL, 0)) < 0 || fcntl(sockfd, F_SETFL, flags | O_NONBLOCK) < 0))
  30.         {
  31.                 close(sockfd);
  32.                 return -1;
  33.         }
  34. }






  35. int main(int argc, char *argv[])
  36. {
  37.         char *ptr;
  38.         fd_set readfds;
  39.         struct timeval tv;
  40.         char buffer[1024];
  41.         int sockfd, efd, nbytes, nfds, i;
  42.         char ch[]     = "GET /opensource/2010/0422/528617.shtml HTTP/1.1\r\nAccept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*\r\nAccept-Language: zh-cn\r\nUser-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)\r\nHost: news.chinaunix.net\r\nConnection: Keep-Alive\r\n\r\n";
  43.         char server[] = "news.chinaunix.net";
  44.         struct hostent *he;
  45.         struct in_addr inadr;
  46.         struct sockaddr_in dest_addr;
  47.        
  48.         long read_incoming, write_incoming, write_outcoming;


  49.         int fp;
  50.         if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
  51.         {
  52.                 perror("socket");
  53.                 exit(1);
  54.         }
  55.        
  56.         if (inet_aton(server, &inadr) == 0)
  57.         {
  58.                 if ((he = gethostbyname(server)) == NULL)
  59.                 {
  60.                         printf("unable to resolve: %s\n", server);
  61.                         return (-1);
  62.                 }

  63.                 memcpy(&inadr.s_addr, he->h_addr_list[0], he->h_length);
  64.         }

  65.         dest_addr.sin_family      = AF_INET;
  66.         dest_addr.sin_port        = htons(DestPort);
  67. //        dest_addr.sin_addr.s_addr = inet_addr(DestIp);
  68.        
  69.         memcpy(&dest_addr.sin_addr, &inadr.s_addr, 4);

  70.         // Create and setup the connection
  71.         if (connect(sockfd, (struct sockaddr *)&dest_addr,sizeof(struct sockaddr)) == -1)
  72.         {
  73.                 perror("connect");
  74.                 exit(1);
  75.         }

  76.         set_nonblocking(sockfd);
  77.        

  78.        
  79.         nbytes = write(sockfd, ch, strlen(ch));
  80.         printf("nbytes = %d\n", nbytes);

  81.         fp = open("./chunked.html", O_WRONLY | O_CREAT | O_TRUNC, 0644);
  82.        
  83.         if ( pipe(pipefd) < 0 )
  84.         {
  85.                 perror("pipe");
  86.                 exit(1);
  87.         }
  88.        
  89.         do {
  90.                 read_incoming = ssplice(sockfd, NULL, pipefd[1], NULL, SPLICE_SIZE, SPLICE_F_NONBLOCK | SPLICE_F_MORE | SPLICE_F_MOVE);

  91.                 if(read_incoming < 0)
  92.                 {
  93.                         if(errno == EINTR || errno == EAGAIN)
  94.                         {
  95.                                 usleep(100);
  96.                                 continue;
  97.                         }
  98.                         error("1splice");
  99.                         break;
  100.                 }
  101.                 else if(read_incoming == 0)
  102.                 {
  103.                         break;
  104.                 }

  105.                 write_outcoming = read_incoming;
  106.                 while(write_outcoming > 0)
  107.                 {

  108.                         write_incoming = splice(pipefd[0], NULL, fp, NULL, write_outcoming, SPLICE_F_NONBLOCK | SPLICE_F_MORE | SPLICE_F_MOVE);
  109.                         if(write_incoming < 0)
  110.                         {
  111.                                 if(write_incoming == -EAGAIN)
  112.                                 {
  113.                                         continue;
  114.                                 }
  115.                                 error("2splice");
  116.                                 break;
  117.                         }

  118.                         write_outcoming -= write_incoming;
  119.                 }
  120.         } while (1);


  121.         close(fp);

  122.         close(sockfd);
  123. }
复制代码
这个程序 作为http客户端,直接把socket数据 存储到磁盘中去。
在我的Ubuntu 就正常。

在CentOS 就报错1splice: Invalid argument

不知道什么原因? 各位大哥帮我看看

CentOS
Linux version 2.6.18-128.7.1.el5 (gcc version 4.1.2 20080704 (Red Hat 4.1.2-44)) #1 SMP Mon Aug 24 08:21:56 EDT 2009

Ubuntu

Linux version 2.6.31-14-generic-pae (buildd@rothera) (gcc version 4.4.1 (Ubuntu 4.4.1-4ubuntu ) #48-Ubuntu SMP Fri Oct 16 15:22:42 UTC 2009

论坛徽章:
0
2 [报告]
发表于 2010-06-11 14:43 |只看该作者
#if defined(__i386__)
#define __NR_sys_splice                313
#define __NR_sys_tee                315
#define __NR_sys_vmsplice        316
这个不见得适用于Kernel 2.6.18吧。而且sys_splice的参数个数是不是改过你得查查。
上面的预定义查CentOS的内核源码,有但是数字不同的话用上对应的,没有那就是不支持了。

论坛徽章:
0
3 [报告]
发表于 2010-06-11 15:28 |只看该作者

  1. /*
  2. * Splice stdin to net
  3. */
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <unistd.h>
  7. #include <netdb.h>
  8. #include <unistd.h>
  9. #include <fcntl.h>
  10. #include <signal.h>
  11. #include <netinet/in.h>
  12. #include <arpa/inet.h>
  13. #include <string.h>
  14. #include <sys/time.h>
  15. #include <errno.h>

  16. #include "splice.h"

  17. static int usage(char *name)
  18. {
  19.         fprintf(stderr, "%s: target port\n", name);
  20.         return 1;
  21. }

  22. int main(int argc, char *argv[])
  23. {
  24.         struct sockaddr_in addr;
  25.         unsigned short port;
  26.         int fd, ret;

  27.         if (argc < 3)
  28.                 return usage(argv[0]);

  29.         if (check_input_pipe())
  30.                 return usage(argv[0]);

  31.         port = atoi(argv[2]);

  32.         memset(&addr, 0, sizeof(addr));
  33.         addr.sin_family = AF_INET;
  34.         addr.sin_port = htons(port);

  35.         if (inet_aton(argv[1], &addr.sin_addr) != 1) {
  36.                 struct hostent *hent = gethostbyname(argv[1]);

  37.                 if (!hent)
  38.                         return error("gethostbyname");

  39.                 memcpy(&addr.sin_addr, hent->h_addr, 4);
  40.         }

  41.         printf("Connecting to %s/%d\n", argv[1], port);

  42.         fd = socket(AF_INET, SOCK_STREAM, 0);
  43.         if (fd < 0)
  44.                 return error("socket");

  45.         if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0)
  46.                 return error("connect");

  47.         do {
  48.                 ret = ssplice(STDIN_FILENO, NULL, fd, NULL, SPLICE_SIZE, SPLICE_F_NONBLOCK);
  49.                 if (ret < 0) {
  50.                         if (errno == EAGAIN) {
  51.                                 usleep(100);
  52.                                 continue;
  53.                         }
  54.                         return error("splice");
  55.                 } else if (!ret)
  56.                         break;
  57.         } while (1);

  58.         close(fd);
  59.         return 0;
  60. }

复制代码
我用这个代码,就可以在CentOS正常运行。这个是 从本地到socket

论坛徽章:
0
4 [报告]
发表于 2010-06-11 15:39 |只看该作者
那你把标志参数一个个去掉看是哪个标志不支持吧。你本地不是只用了一个吗。SPLICE_F_NONBLOCK。或者升级CentOS的内核,可以试试把Ubuntu的内核复制过去。

论坛徽章:
0
5 [报告]
发表于 2010-06-11 16:09 |只看该作者
我把errno 打印出来
报 errno  EINVAL 错误
我查man

EINVAL
Target file system doesn't support splicing; neither of the descriptors refers to a pipe; or offset given for non-seekable device.
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP