What are two caveats of line buffering in Unix?












1















A paragraph from APUE Chapter 5.4 about line buffer:





  1. Line buffered. In this case, the standard I/O library performs I/O when a newline character is encountered on input or output. This allows us to output a single character at a time (with the standard I/O fputc function), knowing that actual I/O will take place only when we finish writing each line. Line buffering is typically used on a stream when it refers to a terminal—standard input and standard output, for example. Line buffering comes with two caveats. First, the size of the buffer that the standard I/O library uses to collect each line is fixed, so I/O might take place if we fill this buffer before writing a newline. Second, whenever input is requested through the standard I/O library from either (a) an unbuffered stream or (b) a line-buffered stream (that requires data to be requested from the kernel), all line-buffered output streams are flushed. The reason for the qualifier on (b) is that the requested data may already be in the buffer, which doesn’t require data to be read from the kernel. Obviously, any input from an unbuffered stream, item (a), requires data to be obtained from the kernel.




I don't really understand the two caveats. Can someone give an example?










share|improve this question

























  • who and why down voted the question? Please explain!

    – user3837980
    Oct 10 '18 at 23:55











  • I did not downvote the question, but I am guessing that the question lacks particular information. Which parts of the quote you do not understand specifically ?

    – Sergiy Kolodyazhnyy
    Feb 24 at 22:39
















1















A paragraph from APUE Chapter 5.4 about line buffer:





  1. Line buffered. In this case, the standard I/O library performs I/O when a newline character is encountered on input or output. This allows us to output a single character at a time (with the standard I/O fputc function), knowing that actual I/O will take place only when we finish writing each line. Line buffering is typically used on a stream when it refers to a terminal—standard input and standard output, for example. Line buffering comes with two caveats. First, the size of the buffer that the standard I/O library uses to collect each line is fixed, so I/O might take place if we fill this buffer before writing a newline. Second, whenever input is requested through the standard I/O library from either (a) an unbuffered stream or (b) a line-buffered stream (that requires data to be requested from the kernel), all line-buffered output streams are flushed. The reason for the qualifier on (b) is that the requested data may already be in the buffer, which doesn’t require data to be read from the kernel. Obviously, any input from an unbuffered stream, item (a), requires data to be obtained from the kernel.




I don't really understand the two caveats. Can someone give an example?










share|improve this question

























  • who and why down voted the question? Please explain!

    – user3837980
    Oct 10 '18 at 23:55











  • I did not downvote the question, but I am guessing that the question lacks particular information. Which parts of the quote you do not understand specifically ?

    – Sergiy Kolodyazhnyy
    Feb 24 at 22:39














1












1








1








A paragraph from APUE Chapter 5.4 about line buffer:





  1. Line buffered. In this case, the standard I/O library performs I/O when a newline character is encountered on input or output. This allows us to output a single character at a time (with the standard I/O fputc function), knowing that actual I/O will take place only when we finish writing each line. Line buffering is typically used on a stream when it refers to a terminal—standard input and standard output, for example. Line buffering comes with two caveats. First, the size of the buffer that the standard I/O library uses to collect each line is fixed, so I/O might take place if we fill this buffer before writing a newline. Second, whenever input is requested through the standard I/O library from either (a) an unbuffered stream or (b) a line-buffered stream (that requires data to be requested from the kernel), all line-buffered output streams are flushed. The reason for the qualifier on (b) is that the requested data may already be in the buffer, which doesn’t require data to be read from the kernel. Obviously, any input from an unbuffered stream, item (a), requires data to be obtained from the kernel.




I don't really understand the two caveats. Can someone give an example?










share|improve this question
















A paragraph from APUE Chapter 5.4 about line buffer:





  1. Line buffered. In this case, the standard I/O library performs I/O when a newline character is encountered on input or output. This allows us to output a single character at a time (with the standard I/O fputc function), knowing that actual I/O will take place only when we finish writing each line. Line buffering is typically used on a stream when it refers to a terminal—standard input and standard output, for example. Line buffering comes with two caveats. First, the size of the buffer that the standard I/O library uses to collect each line is fixed, so I/O might take place if we fill this buffer before writing a newline. Second, whenever input is requested through the standard I/O library from either (a) an unbuffered stream or (b) a line-buffered stream (that requires data to be requested from the kernel), all line-buffered output streams are flushed. The reason for the qualifier on (b) is that the requested data may already be in the buffer, which doesn’t require data to be read from the kernel. Obviously, any input from an unbuffered stream, item (a), requires data to be obtained from the kernel.




I don't really understand the two caveats. Can someone give an example?







files filesystems io buffer streams






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Oct 9 '18 at 5:47









muru

1




1










asked Oct 9 '18 at 4:57









user3837980user3837980

163




163













  • who and why down voted the question? Please explain!

    – user3837980
    Oct 10 '18 at 23:55











  • I did not downvote the question, but I am guessing that the question lacks particular information. Which parts of the quote you do not understand specifically ?

    – Sergiy Kolodyazhnyy
    Feb 24 at 22:39



















  • who and why down voted the question? Please explain!

    – user3837980
    Oct 10 '18 at 23:55











  • I did not downvote the question, but I am guessing that the question lacks particular information. Which parts of the quote you do not understand specifically ?

    – Sergiy Kolodyazhnyy
    Feb 24 at 22:39

















who and why down voted the question? Please explain!

– user3837980
Oct 10 '18 at 23:55





who and why down voted the question? Please explain!

– user3837980
Oct 10 '18 at 23:55













I did not downvote the question, but I am guessing that the question lacks particular information. Which parts of the quote you do not understand specifically ?

– Sergiy Kolodyazhnyy
Feb 24 at 22:39





I did not downvote the question, but I am guessing that the question lacks particular information. Which parts of the quote you do not understand specifically ?

– Sergiy Kolodyazhnyy
Feb 24 at 22:39










2 Answers
2






active

oldest

votes


















4















  1. Basically says, for example,
    that if your program is writing text to the terminal,
    a character at a time, very slowly,
    and the line is (for example) 520 characters long,
    then the library might write the first 512 characters to the terminal
    before your program has finished writing (or even generating) the line.

  2. Says that if your program is writing text to the terminal,
    a character (or some other small piece) at a time,
    and then it reads from the terminal (i.e., the keyboard),
    then the library will write to the terminal
    the portion of the output line that your program has generated up to that point. 
    This is usually what you want,
    as a partial line written to the terminal might be a prompt for input,
    but sometimes it might not be.






share|improve this answer





















  • 1





    @PRY: WTH?  gnis’s edit (1) changed the meaning of my answer (deviated from the original intent of the post), (2) introduced sloppy, non-standard wording, (3) introduced punctuation errors, and (4) had an incorrect edit summary (it says “Improved formatting.”, which it didn’t do, and doesn’t mention the fact that it scrambled what I wrote).  Please don’t approve edits like this — on my posts, or anybody else’s.

    – G-Man
    Feb 25 at 4:28






  • 1





    @RalfFriedl: WTH?  gnis’s edit (1) changed the meaning of my answer (deviated from the original intent of the post), (2) introduced sloppy, non-standard wording, (3) introduced punctuation errors, and (4) had an incorrect edit summary (it says “Improved formatting.”, which it didn’t do, and doesn’t mention the fact that it scrambled what I wrote). Please don’t approve edits like this — on my posts, or anybody else’s.

    – G-Man
    Feb 25 at 4:28



















1














Before exploring two caveats, there are three things to keep in mind.



Unbuffered stream invokes a system call on every read or write.
Whereas line buffered stream invokes a system call on every line(whenever the buffer encounters a newline).



Also, stdin and stdout are both standard I/O stream and are typically line buffered.
These streams are opened automatically when a process starts.



Lastly, while APUE is the bible for learning UNIX, some portions are outdated. I do not claim that my answer is most up-to-date. I will try to take examples from the book so that your questions are properly answered in the context of the textbook.



First caveat



As your quote has stated, there is a restriction on how long a line can be.
And surpassing the limit produces the same effect as having a newline.




Before jumping in with an example on the first caveat, we must remember that write system call actually queues(APUE Chapter 3 Section 6, p86).




Let’s say we have a program named Jasmine that writes a single character to stdout every 30 seconds.



Jasmine writes “Hello!n”(7 bytes), and it takes 210 seconds to complete.



Remember that the buffer has a restriction.
If our buffer is limited to 10 bytes, the kernel can wait for all 210 seconds and issue a single write call at the end(after the newline is encountered).
This is an expected behavior.



If the buffer is limited to 4 bytes, however, the kernel will issue a write call after 4 bytes(“Hell”), then another after the newline(“n”).



This is the first caveat.



A user might expect a single write to occur(“Hello!n” being printed on the terminal).
This is not the case as we’ve saw in our example.
Depending on how busy the system is, the user might see two outputs printing to the terminal within the period of 210 seconds.
This is because even though the stream(stdout) is line buffered, the content of the line is over the restriction(4 bytes limit).
On every 4 bytes, the standard I/O library will invoke write as if a newline is encountered.
The example had 7 bytes(“Hello!n”) in total, and this resulted two write calls.



Second caveat



For the second caveat, the key point here is the interaction with kernel.
kernel will act differently based on our interaction with it, resulting another “unexpected” write with line buffers.



Here is the second caveat from your quote:




kernel will flush all line-buffered streams on two occasions:




  1. When an input is requested via unbuffered standard I/O.

  2. When an input is requested via line buffered standard I/O.




We can reword this in the following:




kernel will flush all line-buffered streams the following prerequisites are satisfied:




  1. An input is requested to kernel.

  2. The request is through either unbuffered or line buffered standard I/O stream.




The first requirement is that “the data must be requested from kernel”.
This allows an exception on the the line buffered standard I/O.



The exception is that kernel will not flush if the request does not require any data from kernel.
This could be a case when the line buffer has all the data stored in the buffer already.




As a quick side example, say a buffer in line buffered stream has “World” characters.
And the user(caller) requests to read 1 byte from the stream.
For the stream to return the requested, single byte(“W”), it does not require any help from kernel.
In such case, kernel will not flush any line buffered streams.




With this exception in mind, let’s continue with the example from the first caveat.



(We should keep the buffer limit as 10 bytes)



After outputting “Hello!n”, our program, Jasmine, writes "Name?" to stdout.



“Name?” has no newline, and is under the limit of 10 bytes.
The standard I/O library does not issue a write call yet.



Then Jasmine requests an input from stdin(another line buffered stream), and the following occurs:




  1. The line buffer on stdin stream is empty, so it requests data from kernel.


  2. kernel flushes all line buffered streams that are opened(which includes “Name?” on stdout).

  3. As the result, “Name?” is printed to the terminal as an output.


  4. kernel waits for user’s input(keyboard) on the terminal.


This is the second caveat.



From the user’s point of view, seeing “Name?” on the terminal could be confusing as no write should have been issued yet. Unfortunately, kernel does issues write call on all currently-opened line buffered streams before kernel attempts to fetch the requested data. This is because the line buffered stream and the interaction with kernel have satisfied both prerequisites.






share|improve this answer























    Your Answer








    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "106"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: false,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f474126%2fwhat-are-two-caveats-of-line-buffering-in-unix%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    4















    1. Basically says, for example,
      that if your program is writing text to the terminal,
      a character at a time, very slowly,
      and the line is (for example) 520 characters long,
      then the library might write the first 512 characters to the terminal
      before your program has finished writing (or even generating) the line.

    2. Says that if your program is writing text to the terminal,
      a character (or some other small piece) at a time,
      and then it reads from the terminal (i.e., the keyboard),
      then the library will write to the terminal
      the portion of the output line that your program has generated up to that point. 
      This is usually what you want,
      as a partial line written to the terminal might be a prompt for input,
      but sometimes it might not be.






    share|improve this answer





















    • 1





      @PRY: WTH?  gnis’s edit (1) changed the meaning of my answer (deviated from the original intent of the post), (2) introduced sloppy, non-standard wording, (3) introduced punctuation errors, and (4) had an incorrect edit summary (it says “Improved formatting.”, which it didn’t do, and doesn’t mention the fact that it scrambled what I wrote).  Please don’t approve edits like this — on my posts, or anybody else’s.

      – G-Man
      Feb 25 at 4:28






    • 1





      @RalfFriedl: WTH?  gnis’s edit (1) changed the meaning of my answer (deviated from the original intent of the post), (2) introduced sloppy, non-standard wording, (3) introduced punctuation errors, and (4) had an incorrect edit summary (it says “Improved formatting.”, which it didn’t do, and doesn’t mention the fact that it scrambled what I wrote). Please don’t approve edits like this — on my posts, or anybody else’s.

      – G-Man
      Feb 25 at 4:28
















    4















    1. Basically says, for example,
      that if your program is writing text to the terminal,
      a character at a time, very slowly,
      and the line is (for example) 520 characters long,
      then the library might write the first 512 characters to the terminal
      before your program has finished writing (or even generating) the line.

    2. Says that if your program is writing text to the terminal,
      a character (or some other small piece) at a time,
      and then it reads from the terminal (i.e., the keyboard),
      then the library will write to the terminal
      the portion of the output line that your program has generated up to that point. 
      This is usually what you want,
      as a partial line written to the terminal might be a prompt for input,
      but sometimes it might not be.






    share|improve this answer





















    • 1





      @PRY: WTH?  gnis’s edit (1) changed the meaning of my answer (deviated from the original intent of the post), (2) introduced sloppy, non-standard wording, (3) introduced punctuation errors, and (4) had an incorrect edit summary (it says “Improved formatting.”, which it didn’t do, and doesn’t mention the fact that it scrambled what I wrote).  Please don’t approve edits like this — on my posts, or anybody else’s.

      – G-Man
      Feb 25 at 4:28






    • 1





      @RalfFriedl: WTH?  gnis’s edit (1) changed the meaning of my answer (deviated from the original intent of the post), (2) introduced sloppy, non-standard wording, (3) introduced punctuation errors, and (4) had an incorrect edit summary (it says “Improved formatting.”, which it didn’t do, and doesn’t mention the fact that it scrambled what I wrote). Please don’t approve edits like this — on my posts, or anybody else’s.

      – G-Man
      Feb 25 at 4:28














    4












    4








    4








    1. Basically says, for example,
      that if your program is writing text to the terminal,
      a character at a time, very slowly,
      and the line is (for example) 520 characters long,
      then the library might write the first 512 characters to the terminal
      before your program has finished writing (or even generating) the line.

    2. Says that if your program is writing text to the terminal,
      a character (or some other small piece) at a time,
      and then it reads from the terminal (i.e., the keyboard),
      then the library will write to the terminal
      the portion of the output line that your program has generated up to that point. 
      This is usually what you want,
      as a partial line written to the terminal might be a prompt for input,
      but sometimes it might not be.






    share|improve this answer
















    1. Basically says, for example,
      that if your program is writing text to the terminal,
      a character at a time, very slowly,
      and the line is (for example) 520 characters long,
      then the library might write the first 512 characters to the terminal
      before your program has finished writing (or even generating) the line.

    2. Says that if your program is writing text to the terminal,
      a character (or some other small piece) at a time,
      and then it reads from the terminal (i.e., the keyboard),
      then the library will write to the terminal
      the portion of the output line that your program has generated up to that point. 
      This is usually what you want,
      as a partial line written to the terminal might be a prompt for input,
      but sometimes it might not be.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Feb 25 at 4:32

























    answered Oct 9 '18 at 5:30









    G-ManG-Man

    13.4k93668




    13.4k93668








    • 1





      @PRY: WTH?  gnis’s edit (1) changed the meaning of my answer (deviated from the original intent of the post), (2) introduced sloppy, non-standard wording, (3) introduced punctuation errors, and (4) had an incorrect edit summary (it says “Improved formatting.”, which it didn’t do, and doesn’t mention the fact that it scrambled what I wrote).  Please don’t approve edits like this — on my posts, or anybody else’s.

      – G-Man
      Feb 25 at 4:28






    • 1





      @RalfFriedl: WTH?  gnis’s edit (1) changed the meaning of my answer (deviated from the original intent of the post), (2) introduced sloppy, non-standard wording, (3) introduced punctuation errors, and (4) had an incorrect edit summary (it says “Improved formatting.”, which it didn’t do, and doesn’t mention the fact that it scrambled what I wrote). Please don’t approve edits like this — on my posts, or anybody else’s.

      – G-Man
      Feb 25 at 4:28














    • 1





      @PRY: WTH?  gnis’s edit (1) changed the meaning of my answer (deviated from the original intent of the post), (2) introduced sloppy, non-standard wording, (3) introduced punctuation errors, and (4) had an incorrect edit summary (it says “Improved formatting.”, which it didn’t do, and doesn’t mention the fact that it scrambled what I wrote).  Please don’t approve edits like this — on my posts, or anybody else’s.

      – G-Man
      Feb 25 at 4:28






    • 1





      @RalfFriedl: WTH?  gnis’s edit (1) changed the meaning of my answer (deviated from the original intent of the post), (2) introduced sloppy, non-standard wording, (3) introduced punctuation errors, and (4) had an incorrect edit summary (it says “Improved formatting.”, which it didn’t do, and doesn’t mention the fact that it scrambled what I wrote). Please don’t approve edits like this — on my posts, or anybody else’s.

      – G-Man
      Feb 25 at 4:28








    1




    1





    @PRY: WTH?  gnis’s edit (1) changed the meaning of my answer (deviated from the original intent of the post), (2) introduced sloppy, non-standard wording, (3) introduced punctuation errors, and (4) had an incorrect edit summary (it says “Improved formatting.”, which it didn’t do, and doesn’t mention the fact that it scrambled what I wrote).  Please don’t approve edits like this — on my posts, or anybody else’s.

    – G-Man
    Feb 25 at 4:28





    @PRY: WTH?  gnis’s edit (1) changed the meaning of my answer (deviated from the original intent of the post), (2) introduced sloppy, non-standard wording, (3) introduced punctuation errors, and (4) had an incorrect edit summary (it says “Improved formatting.”, which it didn’t do, and doesn’t mention the fact that it scrambled what I wrote).  Please don’t approve edits like this — on my posts, or anybody else’s.

    – G-Man
    Feb 25 at 4:28




    1




    1





    @RalfFriedl: WTH?  gnis’s edit (1) changed the meaning of my answer (deviated from the original intent of the post), (2) introduced sloppy, non-standard wording, (3) introduced punctuation errors, and (4) had an incorrect edit summary (it says “Improved formatting.”, which it didn’t do, and doesn’t mention the fact that it scrambled what I wrote). Please don’t approve edits like this — on my posts, or anybody else’s.

    – G-Man
    Feb 25 at 4:28





    @RalfFriedl: WTH?  gnis’s edit (1) changed the meaning of my answer (deviated from the original intent of the post), (2) introduced sloppy, non-standard wording, (3) introduced punctuation errors, and (4) had an incorrect edit summary (it says “Improved formatting.”, which it didn’t do, and doesn’t mention the fact that it scrambled what I wrote). Please don’t approve edits like this — on my posts, or anybody else’s.

    – G-Man
    Feb 25 at 4:28













    1














    Before exploring two caveats, there are three things to keep in mind.



    Unbuffered stream invokes a system call on every read or write.
    Whereas line buffered stream invokes a system call on every line(whenever the buffer encounters a newline).



    Also, stdin and stdout are both standard I/O stream and are typically line buffered.
    These streams are opened automatically when a process starts.



    Lastly, while APUE is the bible for learning UNIX, some portions are outdated. I do not claim that my answer is most up-to-date. I will try to take examples from the book so that your questions are properly answered in the context of the textbook.



    First caveat



    As your quote has stated, there is a restriction on how long a line can be.
    And surpassing the limit produces the same effect as having a newline.




    Before jumping in with an example on the first caveat, we must remember that write system call actually queues(APUE Chapter 3 Section 6, p86).




    Let’s say we have a program named Jasmine that writes a single character to stdout every 30 seconds.



    Jasmine writes “Hello!n”(7 bytes), and it takes 210 seconds to complete.



    Remember that the buffer has a restriction.
    If our buffer is limited to 10 bytes, the kernel can wait for all 210 seconds and issue a single write call at the end(after the newline is encountered).
    This is an expected behavior.



    If the buffer is limited to 4 bytes, however, the kernel will issue a write call after 4 bytes(“Hell”), then another after the newline(“n”).



    This is the first caveat.



    A user might expect a single write to occur(“Hello!n” being printed on the terminal).
    This is not the case as we’ve saw in our example.
    Depending on how busy the system is, the user might see two outputs printing to the terminal within the period of 210 seconds.
    This is because even though the stream(stdout) is line buffered, the content of the line is over the restriction(4 bytes limit).
    On every 4 bytes, the standard I/O library will invoke write as if a newline is encountered.
    The example had 7 bytes(“Hello!n”) in total, and this resulted two write calls.



    Second caveat



    For the second caveat, the key point here is the interaction with kernel.
    kernel will act differently based on our interaction with it, resulting another “unexpected” write with line buffers.



    Here is the second caveat from your quote:




    kernel will flush all line-buffered streams on two occasions:




    1. When an input is requested via unbuffered standard I/O.

    2. When an input is requested via line buffered standard I/O.




    We can reword this in the following:




    kernel will flush all line-buffered streams the following prerequisites are satisfied:




    1. An input is requested to kernel.

    2. The request is through either unbuffered or line buffered standard I/O stream.




    The first requirement is that “the data must be requested from kernel”.
    This allows an exception on the the line buffered standard I/O.



    The exception is that kernel will not flush if the request does not require any data from kernel.
    This could be a case when the line buffer has all the data stored in the buffer already.




    As a quick side example, say a buffer in line buffered stream has “World” characters.
    And the user(caller) requests to read 1 byte from the stream.
    For the stream to return the requested, single byte(“W”), it does not require any help from kernel.
    In such case, kernel will not flush any line buffered streams.




    With this exception in mind, let’s continue with the example from the first caveat.



    (We should keep the buffer limit as 10 bytes)



    After outputting “Hello!n”, our program, Jasmine, writes "Name?" to stdout.



    “Name?” has no newline, and is under the limit of 10 bytes.
    The standard I/O library does not issue a write call yet.



    Then Jasmine requests an input from stdin(another line buffered stream), and the following occurs:




    1. The line buffer on stdin stream is empty, so it requests data from kernel.


    2. kernel flushes all line buffered streams that are opened(which includes “Name?” on stdout).

    3. As the result, “Name?” is printed to the terminal as an output.


    4. kernel waits for user’s input(keyboard) on the terminal.


    This is the second caveat.



    From the user’s point of view, seeing “Name?” on the terminal could be confusing as no write should have been issued yet. Unfortunately, kernel does issues write call on all currently-opened line buffered streams before kernel attempts to fetch the requested data. This is because the line buffered stream and the interaction with kernel have satisfied both prerequisites.






    share|improve this answer




























      1














      Before exploring two caveats, there are three things to keep in mind.



      Unbuffered stream invokes a system call on every read or write.
      Whereas line buffered stream invokes a system call on every line(whenever the buffer encounters a newline).



      Also, stdin and stdout are both standard I/O stream and are typically line buffered.
      These streams are opened automatically when a process starts.



      Lastly, while APUE is the bible for learning UNIX, some portions are outdated. I do not claim that my answer is most up-to-date. I will try to take examples from the book so that your questions are properly answered in the context of the textbook.



      First caveat



      As your quote has stated, there is a restriction on how long a line can be.
      And surpassing the limit produces the same effect as having a newline.




      Before jumping in with an example on the first caveat, we must remember that write system call actually queues(APUE Chapter 3 Section 6, p86).




      Let’s say we have a program named Jasmine that writes a single character to stdout every 30 seconds.



      Jasmine writes “Hello!n”(7 bytes), and it takes 210 seconds to complete.



      Remember that the buffer has a restriction.
      If our buffer is limited to 10 bytes, the kernel can wait for all 210 seconds and issue a single write call at the end(after the newline is encountered).
      This is an expected behavior.



      If the buffer is limited to 4 bytes, however, the kernel will issue a write call after 4 bytes(“Hell”), then another after the newline(“n”).



      This is the first caveat.



      A user might expect a single write to occur(“Hello!n” being printed on the terminal).
      This is not the case as we’ve saw in our example.
      Depending on how busy the system is, the user might see two outputs printing to the terminal within the period of 210 seconds.
      This is because even though the stream(stdout) is line buffered, the content of the line is over the restriction(4 bytes limit).
      On every 4 bytes, the standard I/O library will invoke write as if a newline is encountered.
      The example had 7 bytes(“Hello!n”) in total, and this resulted two write calls.



      Second caveat



      For the second caveat, the key point here is the interaction with kernel.
      kernel will act differently based on our interaction with it, resulting another “unexpected” write with line buffers.



      Here is the second caveat from your quote:




      kernel will flush all line-buffered streams on two occasions:




      1. When an input is requested via unbuffered standard I/O.

      2. When an input is requested via line buffered standard I/O.




      We can reword this in the following:




      kernel will flush all line-buffered streams the following prerequisites are satisfied:




      1. An input is requested to kernel.

      2. The request is through either unbuffered or line buffered standard I/O stream.




      The first requirement is that “the data must be requested from kernel”.
      This allows an exception on the the line buffered standard I/O.



      The exception is that kernel will not flush if the request does not require any data from kernel.
      This could be a case when the line buffer has all the data stored in the buffer already.




      As a quick side example, say a buffer in line buffered stream has “World” characters.
      And the user(caller) requests to read 1 byte from the stream.
      For the stream to return the requested, single byte(“W”), it does not require any help from kernel.
      In such case, kernel will not flush any line buffered streams.




      With this exception in mind, let’s continue with the example from the first caveat.



      (We should keep the buffer limit as 10 bytes)



      After outputting “Hello!n”, our program, Jasmine, writes "Name?" to stdout.



      “Name?” has no newline, and is under the limit of 10 bytes.
      The standard I/O library does not issue a write call yet.



      Then Jasmine requests an input from stdin(another line buffered stream), and the following occurs:




      1. The line buffer on stdin stream is empty, so it requests data from kernel.


      2. kernel flushes all line buffered streams that are opened(which includes “Name?” on stdout).

      3. As the result, “Name?” is printed to the terminal as an output.


      4. kernel waits for user’s input(keyboard) on the terminal.


      This is the second caveat.



      From the user’s point of view, seeing “Name?” on the terminal could be confusing as no write should have been issued yet. Unfortunately, kernel does issues write call on all currently-opened line buffered streams before kernel attempts to fetch the requested data. This is because the line buffered stream and the interaction with kernel have satisfied both prerequisites.






      share|improve this answer


























        1












        1








        1







        Before exploring two caveats, there are three things to keep in mind.



        Unbuffered stream invokes a system call on every read or write.
        Whereas line buffered stream invokes a system call on every line(whenever the buffer encounters a newline).



        Also, stdin and stdout are both standard I/O stream and are typically line buffered.
        These streams are opened automatically when a process starts.



        Lastly, while APUE is the bible for learning UNIX, some portions are outdated. I do not claim that my answer is most up-to-date. I will try to take examples from the book so that your questions are properly answered in the context of the textbook.



        First caveat



        As your quote has stated, there is a restriction on how long a line can be.
        And surpassing the limit produces the same effect as having a newline.




        Before jumping in with an example on the first caveat, we must remember that write system call actually queues(APUE Chapter 3 Section 6, p86).




        Let’s say we have a program named Jasmine that writes a single character to stdout every 30 seconds.



        Jasmine writes “Hello!n”(7 bytes), and it takes 210 seconds to complete.



        Remember that the buffer has a restriction.
        If our buffer is limited to 10 bytes, the kernel can wait for all 210 seconds and issue a single write call at the end(after the newline is encountered).
        This is an expected behavior.



        If the buffer is limited to 4 bytes, however, the kernel will issue a write call after 4 bytes(“Hell”), then another after the newline(“n”).



        This is the first caveat.



        A user might expect a single write to occur(“Hello!n” being printed on the terminal).
        This is not the case as we’ve saw in our example.
        Depending on how busy the system is, the user might see two outputs printing to the terminal within the period of 210 seconds.
        This is because even though the stream(stdout) is line buffered, the content of the line is over the restriction(4 bytes limit).
        On every 4 bytes, the standard I/O library will invoke write as if a newline is encountered.
        The example had 7 bytes(“Hello!n”) in total, and this resulted two write calls.



        Second caveat



        For the second caveat, the key point here is the interaction with kernel.
        kernel will act differently based on our interaction with it, resulting another “unexpected” write with line buffers.



        Here is the second caveat from your quote:




        kernel will flush all line-buffered streams on two occasions:




        1. When an input is requested via unbuffered standard I/O.

        2. When an input is requested via line buffered standard I/O.




        We can reword this in the following:




        kernel will flush all line-buffered streams the following prerequisites are satisfied:




        1. An input is requested to kernel.

        2. The request is through either unbuffered or line buffered standard I/O stream.




        The first requirement is that “the data must be requested from kernel”.
        This allows an exception on the the line buffered standard I/O.



        The exception is that kernel will not flush if the request does not require any data from kernel.
        This could be a case when the line buffer has all the data stored in the buffer already.




        As a quick side example, say a buffer in line buffered stream has “World” characters.
        And the user(caller) requests to read 1 byte from the stream.
        For the stream to return the requested, single byte(“W”), it does not require any help from kernel.
        In such case, kernel will not flush any line buffered streams.




        With this exception in mind, let’s continue with the example from the first caveat.



        (We should keep the buffer limit as 10 bytes)



        After outputting “Hello!n”, our program, Jasmine, writes "Name?" to stdout.



        “Name?” has no newline, and is under the limit of 10 bytes.
        The standard I/O library does not issue a write call yet.



        Then Jasmine requests an input from stdin(another line buffered stream), and the following occurs:




        1. The line buffer on stdin stream is empty, so it requests data from kernel.


        2. kernel flushes all line buffered streams that are opened(which includes “Name?” on stdout).

        3. As the result, “Name?” is printed to the terminal as an output.


        4. kernel waits for user’s input(keyboard) on the terminal.


        This is the second caveat.



        From the user’s point of view, seeing “Name?” on the terminal could be confusing as no write should have been issued yet. Unfortunately, kernel does issues write call on all currently-opened line buffered streams before kernel attempts to fetch the requested data. This is because the line buffered stream and the interaction with kernel have satisfied both prerequisites.






        share|improve this answer













        Before exploring two caveats, there are three things to keep in mind.



        Unbuffered stream invokes a system call on every read or write.
        Whereas line buffered stream invokes a system call on every line(whenever the buffer encounters a newline).



        Also, stdin and stdout are both standard I/O stream and are typically line buffered.
        These streams are opened automatically when a process starts.



        Lastly, while APUE is the bible for learning UNIX, some portions are outdated. I do not claim that my answer is most up-to-date. I will try to take examples from the book so that your questions are properly answered in the context of the textbook.



        First caveat



        As your quote has stated, there is a restriction on how long a line can be.
        And surpassing the limit produces the same effect as having a newline.




        Before jumping in with an example on the first caveat, we must remember that write system call actually queues(APUE Chapter 3 Section 6, p86).




        Let’s say we have a program named Jasmine that writes a single character to stdout every 30 seconds.



        Jasmine writes “Hello!n”(7 bytes), and it takes 210 seconds to complete.



        Remember that the buffer has a restriction.
        If our buffer is limited to 10 bytes, the kernel can wait for all 210 seconds and issue a single write call at the end(after the newline is encountered).
        This is an expected behavior.



        If the buffer is limited to 4 bytes, however, the kernel will issue a write call after 4 bytes(“Hell”), then another after the newline(“n”).



        This is the first caveat.



        A user might expect a single write to occur(“Hello!n” being printed on the terminal).
        This is not the case as we’ve saw in our example.
        Depending on how busy the system is, the user might see two outputs printing to the terminal within the period of 210 seconds.
        This is because even though the stream(stdout) is line buffered, the content of the line is over the restriction(4 bytes limit).
        On every 4 bytes, the standard I/O library will invoke write as if a newline is encountered.
        The example had 7 bytes(“Hello!n”) in total, and this resulted two write calls.



        Second caveat



        For the second caveat, the key point here is the interaction with kernel.
        kernel will act differently based on our interaction with it, resulting another “unexpected” write with line buffers.



        Here is the second caveat from your quote:




        kernel will flush all line-buffered streams on two occasions:




        1. When an input is requested via unbuffered standard I/O.

        2. When an input is requested via line buffered standard I/O.




        We can reword this in the following:




        kernel will flush all line-buffered streams the following prerequisites are satisfied:




        1. An input is requested to kernel.

        2. The request is through either unbuffered or line buffered standard I/O stream.




        The first requirement is that “the data must be requested from kernel”.
        This allows an exception on the the line buffered standard I/O.



        The exception is that kernel will not flush if the request does not require any data from kernel.
        This could be a case when the line buffer has all the data stored in the buffer already.




        As a quick side example, say a buffer in line buffered stream has “World” characters.
        And the user(caller) requests to read 1 byte from the stream.
        For the stream to return the requested, single byte(“W”), it does not require any help from kernel.
        In such case, kernel will not flush any line buffered streams.




        With this exception in mind, let’s continue with the example from the first caveat.



        (We should keep the buffer limit as 10 bytes)



        After outputting “Hello!n”, our program, Jasmine, writes "Name?" to stdout.



        “Name?” has no newline, and is under the limit of 10 bytes.
        The standard I/O library does not issue a write call yet.



        Then Jasmine requests an input from stdin(another line buffered stream), and the following occurs:




        1. The line buffer on stdin stream is empty, so it requests data from kernel.


        2. kernel flushes all line buffered streams that are opened(which includes “Name?” on stdout).

        3. As the result, “Name?” is printed to the terminal as an output.


        4. kernel waits for user’s input(keyboard) on the terminal.


        This is the second caveat.



        From the user’s point of view, seeing “Name?” on the terminal could be confusing as no write should have been issued yet. Unfortunately, kernel does issues write call on all currently-opened line buffered streams before kernel attempts to fetch the requested data. This is because the line buffered stream and the interaction with kernel have satisfied both prerequisites.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Mar 2 at 17:17









        gnisgnis

        134




        134






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Unix & Linux Stack Exchange!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f474126%2fwhat-are-two-caveats-of-line-buffering-in-unix%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            How to reconfigure Docker Trusted Registry 2.x.x to use CEPH FS mount instead of NFS and other traditional...

            is 'sed' thread safe

            How to make a Squid Proxy server?