1

I tried to increase a linux pipe buffer size.

Here is my code:

#define _GNU_SOURCE

#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>

#define IO_BUFSIZE 4096

#include<stdio.h> //printf
#include<string.h>    //strlen
#include<sys/socket.h>    //socket
#include<arpa/inet.h> //inet_addr

typedef struct {
        loff_t offset;
        int size;
} msg_header;

int main(int argc , char *argv[])
{

   loff_t in_off = 0;
   loff_t out_off = 0;

   int in_fd = -1; //file id
   int err = -1;
   int splice_bytes = 0;
   int len1 = 0;
   int len2 = 0;
   int len3 = 0;

   in_fd = open("/home/wenji/splice-sample/libpfm-4.5.0.tar", O_RDONLY); //open a file

   int filedes[2];
   struct stat stbuf;

   if(pipe(filedes) < 0)
   {
        perror("pipe error");
   }

   //set the pipe size,
   fcntl(filedes[1], F_SETPIPE_SZ, 1048576);


   if(fstat(in_fd, &stbuf) < 0)
   {
        perror("wrong file id");
   }

   len1 = stbuf.st_size;

   printf("the file size len=%i\n", len1);

    int sock;
    struct sockaddr_in server;
    char message[1000] , server_reply[2000];
    msg_header e_block;

    //Create socket
    sock = socket(AF_INET , SOCK_STREAM , 0);
    if (sock == -1)
    {
        printf("Could not create socket");
    }
    puts("Socket created");

    server.sin_addr.s_addr = inet_addr("10.1.1.2");
    server.sin_family = AF_INET;
    server.sin_port = htons( 8888 );

    //Connect to remote server
    if (connect(sock , (struct sockaddr *)&server , sizeof(server)) < 0)
    {
        perror("connect failed. Error");
        return 1;
    }

    puts("Connected\n");


   printf("the file size = %i \n", len1);

    //keep communicating with server
    while(len1>0)
    {

        //record the offset
        e_block.offset = in_off;

        //first, splice data from file to pipe

        splice_bytes = splice(in_fd, &in_off, filedes[1], NULL, 32736, SPLICE_F_MOVE|SPLICE_F_MORE);
        if(splice_bytes < 0)
        {
                perror("splice error");
        }


        //record the size
        e_block.size = splice_bytes;

        //Send e-block header over
        if( send(sock , &e_block , sizeof(msg_header) , 0) < 0)
        {
            puts("Send failed");
            return 1;
        }

        printf("e-block size %i, offset %ld \n", e_block.size, e_block.offset);

        len2 = splice_bytes;
        while(len2 > 0) {
        //send the data over network
                len3 = splice(filedes[0],NULL, sock, 0, len2, SPLICE_F_MOVE|SPLICE_F_MORE);
                len2 = len2 - len3;
        }

        len1 -= splice_bytes;

     }

    close(sock);
    close(filedes[0]);
    close(filedes[1]);
    close(in_fd);

    return 0;
}

When I compile the code, I got the following errors:

client.c: In function ‘main’:
client.c:45: error: ‘F_SETPIPE_SZ’ undeclared (first use in this function)
client.c:45: error: (Each undeclared identifier is reported only once
client.c:45: error: for each function it appears in.)

"#define _GNU_SOURCE" has been included in my code.

Here is my "uname -r"

"Linux capecod 3.12.12 #3 SMP Thu Feb 27 21:55:17 CST 2014 x86_64 x86_64 x86_64 GNU/Linux"

Could anybody help me out? thanks

wwu

Wenji Wu
  • 59
  • 5
  • did you check this link http://stackoverflow.com/questions/25411892/f-setpipe-sz-undeclared , by the way where is the code ? – asio_guy Sep 08 '15 at 04:42
  • Have you included fcntl.h and unistd.h headers? – Jack Sep 08 '15 at 04:42
  • I checked the above link, "#define _GNU_SOURCE" is included in my code. But still I have the errors. – Wenji Wu Sep 08 '15 at 04:46
  • Yes, I included fcntl.h and unistd.h headers – Wenji Wu Sep 08 '15 at 04:47
  • @WenjiWu :Can you show us the code where the headers and the macro `_GNU_SOURCE` is in the code. Also can you show the command you use to compile the code – Santosh A Sep 08 '15 at 04:48
  • 1
    I can't reproduce this. Your code compiles here (i686 4.1.6-1-ARCH) (but gcc produces a few warnings: `%ld` is the wrong format, and some variables are unused). – melpomene Sep 08 '15 at 05:37
  • As @Santosh A asked, please provide the command that you used to compile the source. Also, provide the output of "cc --version'. – TonyB Sep 08 '15 at 06:47
  • In Ubuntu 14.04.3 LTS, you need to add `#include `, as its normal fcntl.h header file does not include it (even if _GNU_SOURCE or others are set). If you don't want to change the sources, try adding `-include linux/fcntl.h` when compiling instead. – Nominal Animal Sep 08 '15 at 10:18
  • @TonyB,[root@capecod splice-sample]# cc --version cc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-3) Copyright (C) 2010 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. – Wenji Wu Sep 08 '15 at 15:04
  • @Nominal Animal, follow your suggestion, still does not work. – Wenji Wu Sep 08 '15 at 15:05
  • The command I was using to compile is "gcc -o client client.c" – Wenji Wu Sep 08 '15 at 15:06
  • @WenjiWu: What does `grep -e F_SETPIPE_SZ -r /usr/include` output? It looks like maybe you have not installed C development headers, or any kernel headers. What does `cat /etc/issue` output? It should tell us exactly what distribution and version you're using; the packages you need and the commands to check vary from distribution to distribution. – Nominal Animal Sep 08 '15 at 19:17
  • @Nominal Animal, here is the output "[root@mdtm-server ~]# grep -e F_SETPIPE_SZ -r /usr/include /usr/include/bits/fcntl-linux.h:# define F_SETPIPE_SZ 1031 /* Set pipe page size array. */", – Wenji Wu Sep 09 '15 at 01:28
  • @Nominal Animal, here is output "[root@mdtm-server ~]# cat /etc/issue Scientific Linux Fermi release 6.6 (Ramsey) Kernel \r on an \m" – Wenji Wu Sep 09 '15 at 01:29
  • @WenjiWu: You seem to have [Scientific Linux Fermi 6.6](https://fermilinux.fnal.gov/), for which the latest kernel is 2.6.32. The `F_SETPIPE_SZ` is only provided in 2.6.36 and later kernels, which is why SLF6.6 does not have it in its headers -- it just does not support it. However, you're evidently running kernel 3.12.2. This indicates you're running a Frankenstein system, cobbled together from RPM packages you've obtained from wherever, from different distros. *That is not intended to work.* – Nominal Animal Sep 09 '15 at 08:00
  • That said, just add `#define F_SETPIPE_SZ 1031` and `#define F_GETPIPE_SZ 1032` to your Frankenstein headers, to get your code to work for now; these are the correct values for Linux x86_64 kernels. The long-term fix is to reinstall a proper Linux distribution on your machine, not one cobbled together from disparate RPMs... Use your package manager, and stop downloading the first RPM you find off the internet. – Nominal Animal Sep 09 '15 at 08:03
  • @Nominal Animal, thank you. you are right. When I add the two lines of code you suggested, it works now. I was trying to directly include header files from "/usr/src/3.12.2/include", but it did not work. – Wenji Wu Sep 09 '15 at 11:49

0 Answers0