Linux-Development-Sys Digest #855, Volume #7 Sun, 14 May 00 18:13:19 EDT
Contents:
Re: ANSI C & void main() ("Frank")
Re: Linux (thread vs fork) (Todd Knarr)
Re: ANSI C & void main() (Kaz Kylheku)
Re: ANSI C & void main() (Mike McDonald)
Re: ANSI C & void main() (Kaz Kylheku)
Re: ANSI C & void main() (David Wragg)
Re: Linux (thread vs fork) (Daniel R. Grayson)
Big time Network Collisions (Mark)
Re: ANSI C & void main() (Joe Pfeiffer)
Re: ANSI C & void main() (Joe Pfeiffer)
Re: ANSI C & void main() (Joe Pfeiffer)
Re: Big time Network Collisions (Dan McGuirk)
Re: ANSI C & void main() (Kaz Kylheku)
----------------------------------------------------------------------------
From: "Frank" <[EMAIL PROTECTED]>
Subject: Re: ANSI C & void main()
Date: Sun, 14 May 2000 15:54:02 GMT
Kaz Kylheku <[EMAIL PROTECTED]>...
^
^ Explain how main can return int if its return type has been declared
^ void? Returning a value in a function that returns nothing is a constraint
^ violation; it requires a diagnostic.
Actually main() isn't returning an 'int', exit(0) is being called instead.
I'm going to have to back out of this discussion because I don't have the
necessary documentation, but I will leave by quoting an old manual that I do
have available. I recognize that this manual is not a standard but it does
represent an interpretation of one.
=================================
SAS/C Development System Library Reference Version 6.0 (C)1992:
exit: Terminates program execution
Synopsis: [skipped]
Description: [skipped]
Portability: ANSI
Example:
void main(int argc, char *argv[])
{
FILE *f;
if (argc > 1)
{
f = fopen(argv[1],"r");
if (f == NULL)
{
fprintf(stderr,
"Can't open file \"%s\"\n",
argv[1]);
exit(EXIT_FAILURE);
}
fclose(f);
}
else
{
fprintf(stderr,"No file specified\n");
exit(EXIT_FAILURE);
}
}
===========================
If main() were to use the return statement (return INTEGER) then it would have
to be defined as 'int main()'. Since it is not using 'return' it must be
defined as 'void'. To define main() as 'int' and 'return' nothing is an error,
but the standard allows for the absence of a return statement so 'void' must
be permitted. If 'void main(){/*no return*/}' is used then 'return(0)' is
implied.
Frank
------------------------------
From: Todd Knarr <[EMAIL PROTECTED]>
Subject: Re: Linux (thread vs fork)
Date: 14 May 2000 17:19:18 GMT
In comp.os.linux.development.system <8fllla$[EMAIL PROTECTED]> bil@p wrote:
> That is strange term to use, who invented it?
Preforking's an old term, I ran into it literally a decade ago. I think
it comes from a variation on one of the tricks for improving performance.
A naive server forks a new process for each request, and lets that
process terminate when it's handled the request. The smarter variation
I was taught keeps a list of processes it's forked, hands requests off
to unoccupied processes in the list and only forks more and adds them to
the list if there are no unoccupied processes. Prefork I first heard
used for servers that modified the second variation by forking off
new processes before they were needed, usually right at startup, so it
always had some minimum number of processes available to it.
--
Collin was right. Never give a virus a missile launcher.
-- Erk, Reality Check #8
------------------------------
From: [EMAIL PROTECTED] (Kaz Kylheku)
Subject: Re: ANSI C & void main()
Reply-To: [EMAIL PROTECTED]
Date: Sun, 14 May 2000 17:39:05 GMT
On Sun, 14 May 2000 13:54:42 GMT, Frank <[EMAIL PROTECTED]> wrote:
>Kaz Kylheku <[EMAIL PROTECTED]>...
>^
>^ Only if you apply a sixth grade or lower level of reading
>^ comprehension to the text.
>
>Are you applying sixth grade behavior here? To accurately read a standard you
>must "apply a sixth grade or lower level of reading comprehension to the
>text." If you read anything into it, as adults typically do, you are very
>likely creating errors.
This approach doesn't appear to be working for you, since you are
interpreting things ``a program shall do X'' to mean
``the program can do other than X, yet remain well defined anyway.''
Perhaps you are interpreting the term ``shall'' simply to mean ``will'', which
is the modern everyday meaning of the word. In fact, shall implies an
obligation. The online Merriam-Webster describes one of the meanings as ``used
in laws, regulations, or directives to express what is mandatory''. (It also
says that the ``will have to'' interpretation is archaic; which is consistent,
since laws and regulations tend to use archaic language.)
So even without the benefit of seeing the clause that formally defines
precisely what ``shall'' means within the C++ standard, you don't have much of
an excuse for misinterpreting it.
--
#exclude <windows.h>
------------------------------
Reply-To: [EMAIL PROTECTED]
From: [EMAIL PROTECTED] (Mike McDonald)
Subject: Re: ANSI C & void main()
Date: Sun, 14 May 2000 17:46:46 GMT
In article <[EMAIL PROTECTED]>,
Erik Max Francis <[EMAIL PROTECTED]> writes:
> Mark Graybill wrote:
>> "5 ... If control reaches the end of main without encountering a
>> return
>> statement, the effect is that of executing
>> return 0;"
>>
>> Since you cannot return a value with a return type of void, then
>> paragraph 5
>> defines the behavior after void main() returns to the calling code.
>
> This is a red herring. It only applies given what the Standard has
> stated earlier -- namely, that main must return int. (Besides, a return
> 0, implicit or not, at the end of a function which returns void is
> illegal -- another hint that you're reading this wrong.)
Except main() never returns. In the context of main(), the return statement
has the same effect as calling exit(). Reaching the end of main() is the same as
executing "return 0;", which is effectively "exit(0);". So talking about the
"return type" of main() seems kind of waste.
Mike McDonald
[EMAIL PROTECTED]
------------------------------
From: [EMAIL PROTECTED] (Kaz Kylheku)
Subject: Re: ANSI C & void main()
Reply-To: [EMAIL PROTECTED]
Date: Sun, 14 May 2000 18:18:21 GMT
On Sun, 14 May 2000 17:46:46 GMT, Mike McDonald <[EMAIL PROTECTED]> wrote:
>In article <[EMAIL PROTECTED]>,
> Erik Max Francis <[EMAIL PROTECTED]> writes:
>> Mark Graybill wrote:
>
>>> "5 ... If control reaches the end of main without encountering a
>>> return
>>> statement, the effect is that of executing
>>> return 0;"
>>>
>>> Since you cannot return a value with a return type of void, then
>>> paragraph 5
>>> defines the behavior after void main() returns to the calling code.
>>
>> This is a red herring. It only applies given what the Standard has
>> stated earlier -- namely, that main must return int. (Besides, a return
>> 0, implicit or not, at the end of a function which returns void is
>> illegal -- another hint that you're reading this wrong.)
>
> Except main() never returns. In the context of main(), the return statement
>has the same effect as calling exit(). Reaching the end of main() is the same as
>executing "return 0;", which is effectively "exit(0);". So talking about the
>"return type" of main() seems kind of waste.
This was the subject of a defect report to the first ANSI C standard and
was fixed in one of the Technical Corrigenda, I think.
Returning from main is not exactly the same as calling exit. Why not? Because
registered atexit handlers may be called from exit(). These handlers may refer
to automatic storage within main, provided that it has not returned. Also,
stdio streams are flushed. If any of these streams have buffers that are local
to main, the behavior is undefined when it returns.
Talking about the return type of main is not a waste. It's a function, and as
such it has a return type, and that return type is part of its type. A
function call is only well-defined when the calling expression is compatible
with the defined type of the function; this compatibility match is made on the
return type as well as the parameter count and types. If there is a mismatch,
there is no requirement that any portion of the call must succeed. The
undefined behavior occurs immediately upon evaluation of the mismatched
function call expression. In the case of an incorrect main, the undefined
behavior occurs no later than just before the initial call to main; though,
strictly speaking, the undefined behavior actually starts at translation time;
as soon as the implementation sees the invalid declaration, it can cause demons
to fly out of your nose, or bring up a game of Tetris instead of finishing
the compile job.
Some compilers take advantage of this freedom and emit a diagnostic and stop
translating when they see an incorrect main, rather than resorting to nasal
demons and Tetris games. GCC with -pedantic-errors does this, and the EiC C
interpreter does it without any special options.
--
#exclude <windows.h>
------------------------------
From: David Wragg <[EMAIL PROTECTED]>
Subject: Re: ANSI C & void main()
Date: 14 May 2000 15:02:45 +0000
"Mark Graybill" <[EMAIL PROTECTED]> writes:
> "3 ... The linkage (3.5) of main is implementation�defined."
>
> There is no guideline of how main is linked to the calling code. For
> instance, some crt0 code pushes and pops the return code off the stack.
> Others saves the return code to a specified memory location. This is
> defined by the implementation.
That isn't what linkage means in "the standard" (ISO C++ 98). How can
you expect to interpret any document correctly when you don't known
what the words it uses mean?
David Wragg
------------------------------
Subject: Re: Linux (thread vs fork)
From: [EMAIL PROTECTED] (Daniel R. Grayson)
Date: 14 May 2000 15:22:38 -0500
[EMAIL PROTECTED] (Stefaan A Eeckels) writes:
> In article <8fj2to$45t$[EMAIL PROTECTED]>,
> [EMAIL PROTECTED] writes:
...
> > Another question is that, is there an efficient way for select (or poll)
> > in unix. I want to do the same thing that the select does, but I do not
> > want the penalty (two system calls) of select.
> Select is efficient (or as efficient as you're likely to get in
> a stock UNIX system).
Unless you can arrange for the data from the various sources all to arrive on
the same input file descriptor. Then you can get the data with one blocking
read() system call. Of course, you have to worry about unintentional
interleaving of data between sources, but you can get around that by writing
data in constant length calls to write() where the length is a power of 2
dividing 512. Remember to have each such block of data contain information
that identifies its source.
------------------------------
From: Mark <[EMAIL PROTECTED]>
Subject: Big time Network Collisions
Date: Sun, 14 May 2000 21:46:50 +0100
I've just finished writing a test application to send out ethernet
frames onto a network. To do this I've used low level access to the data
link layer using SOCK_RAW (Finally got the thing to work!!). Basically
the situation is the app send out test messages to another system. I've
found there are a massive number of collisions happening (Almost 50%
loss). Just as the app get above 2000 Frame per second. Each frame is
146 Bytes long, therefore I figure that's 16,000 bits/Sec or 0.16%
utilisation on a 10Mbps LAN. Which is why I'm confused as to why there
are so many errors. Does anyone have any ideas? The application itself
uses the sendto() function to send the frame to the driver. I've looked
at the kernel side of things (netstat) and it's not reporting any
errors.
Many thanks
Mark
PS The other system only sends out a frame once a second (146 bytes as
well)
------------------------------
From: Joe Pfeiffer <[EMAIL PROTECTED]>
Subject: Re: ANSI C & void main()
Date: 14 May 2000 15:11:37 -0600
Actually, I had a hard time understanding that line of the standard --
what exactly does it mean when it says the type of the function isn't
specified by the standard, but it must return an int? I'm not clear
on just what the type of a function is, if not its return type.
--
Joseph J. Pfeiffer, Jr., Ph.D. Phone -- (505) 646-1605
Department of Computer Science FAX -- (505) 646-1002
New Mexico State University http://www.cs.nmsu.edu/~pfeiffer
VL 2000 Homepage: http://www.cs.orst.edu/~burnett/vl2000/
------------------------------
From: Joe Pfeiffer <[EMAIL PROTECTED]>
Subject: Re: ANSI C & void main()
Date: 14 May 2000 15:13:12 -0600
[EMAIL PROTECTED] (Ulrich Weigand) writes:
> type must be int, the rest of the type (i.e. the argument types) is
> implementation-defined.
Ah, thank you. I posted a question about 30 seconds ago wondering
what that meant...
--
Joseph J. Pfeiffer, Jr., Ph.D. Phone -- (505) 646-1605
Department of Computer Science FAX -- (505) 646-1002
New Mexico State University http://www.cs.nmsu.edu/~pfeiffer
VL 2000 Homepage: http://www.cs.orst.edu/~burnett/vl2000/
------------------------------
From: Joe Pfeiffer <[EMAIL PROTECTED]>
Subject: Re: ANSI C & void main()
Date: 14 May 2000 15:09:33 -0600
"Frank" <[EMAIL PROTECTED]> writes:
> ^
> ^ Using your OS would mean that no one could ever write an
> ^ ANSI-compliant C program.
>
> So then there is a problem with sticking to the standard in some
> instances.
Of course. If your system doesn't suport ANSI-standard C, then you
obviously can't write ANSI-standard C for it. OTOH, unless Bigix is
intended some *extremely* specialized purpose, I'd say it had a
horrible design flaw.
> The standard does allow for easily portable code but I have never needed
> portable code in anything I've done.
I used to say things like that... until the day we switched from a VAX
to Suns down here, and all my code that passed *ints to procedures
expecting *chars quit working.
> Portability is certainly essential in
> many cases but it is also unnecessarily restrictive in others. If I wrote this
> Bigix operating system the standard would eventually be changed to allow for
> it, but in the interim no code will be written for it by anyone unable to look
> beyond the standards. Those who do write code for it will be setting the
> standard.
Writing non standard-compliant code may certainly be necessary in some
cases. But not following it without having some good reason is just
foolish.
--
Joseph J. Pfeiffer, Jr., Ph.D. Phone -- (505) 646-1605
Department of Computer Science FAX -- (505) 646-1002
New Mexico State University http://www.cs.nmsu.edu/~pfeiffer
VL 2000 Homepage: http://www.cs.orst.edu/~burnett/vl2000/
------------------------------
From: Dan McGuirk <[EMAIL PROTECTED]>
Subject: Re: Big time Network Collisions
Date: 14 May 2000 14:31:58 -0700
Mark <[EMAIL PROTECTED]> writes:
> I've just finished writing a test application to send out ethernet
> frames onto a network. To do this I've used low level access to the data
> link layer using SOCK_RAW (Finally got the thing to work!!). Basically
> the situation is the app send out test messages to another system. I've
> found there are a massive number of collisions happening (Almost 50%
> loss). Just as the app get above 2000 Frame per second. Each frame is
> 146 Bytes long, therefore I figure that's 16,000 bits/Sec or 0.16%
> utilisation on a 10Mbps LAN.
Hmm. This must be part of the New Math. I get 2,000 frames/sec * 146
bytes/frame * 8 bits/byte = 2,336,000 bits/sec = 2.23 Mbps, or about 22%
of your theoretical maximum throughput.
I'm not sure whether it's reasonable to expect this to work well.
You'd do better with a switch than with a hub, and you might as well
make it a 100Mbit switch while you're at it.
One problem might be that your transmissions are too bursty. i.e., if
you send out 2000 packets all at once, then wait one second, then send
out another 2000, etc., that's probably not going to work too well.
You need to spread things out so the number of packets sent over time
is fairly smooth.
--
Dan McGuirk <[EMAIL PROTECTED]>
"There's no booze left, but I found this fluid in the Xerox machine
in the lobby." "Hit me."
------------------------------
From: [EMAIL PROTECTED] (Kaz Kylheku)
Subject: Re: ANSI C & void main()
Reply-To: [EMAIL PROTECTED]
Date: Sun, 14 May 2000 21:36:10 GMT
On 14 May 2000 15:11:37 -0600, Joe Pfeiffer <[EMAIL PROTECTED]> wrote:
>Actually, I had a hard time understanding that line of the standard --
>what exactly does it mean when it says the type of the function isn't
>specified by the standard, but it must return an int? I'm not clear
>on just what the type of a function is, if not its return type.
Here is a bit of a brain dump:
The type of a function consists of its return type, and the type signature of
its parameter list.
There is one subtlety: qualification on the parameters isn't part of the type,
so that:
int foo(int);
is equivalent to
int foo(const int);
Also, in C, there are some horrible rules for the sake of supporting old-style
declarations. Thus int foo(); is compatible with int foo(double); and it is
simultaneously compatible with int foo(char *); even though these two are not
compatible with each other. Compatibility is symmetric and reflexive, but not
transitive.
When you call a function through an old-style declaration, the actual type of
the call is taken from a combination of the declaration and the actual
parameters. Thus if somewhere in your program you have an int foo(char *)
definition, and you have an old-style int foo(); declaration in scope through
which you call foo(3.0), the behavior is undefined: the actual parameter 3.0
gives rise to a call which needs an int foo(double) function.
It's best not to mix old style declarations with new style definitions or vice
versa because of the strange rules related to arguments having a promotable
type. (E.g. there is no old-style counterpart for a function like int foo(char)
--- you could not pass chars in classic C; they underwent promotion to int or,
rarely, unsigned int, and then conversion back to char). To write a
a prototype declaration for an old-style function int foo(c) { char c; /*...*/ }
you must write the prototype as int foo(int); or, on some extremely rare
compiler where char promotes to unsigned int, as int foo(unsigned);
Another subtlety is that variadic functions like printf are not compatible with
any old-style declaration. If you don't have an ellipsis prototype in scope
for calling a variadic, the behavior is undefined.
What other obscure trivia is there to function type compatibility? Ah yes, this
notion of composite type.
Consider carefully the declaration:
int foo(void (*)(), void (*)(int));
and then the subsequent redeclaration:
int foo(void (*)(int), void (*)());
The first one specifies a fully prototyped function pointer as its
second argument, but an old-style function pointer for its first.
The second declaration does the reverse.
What happens is that after the second declaration, foo is given
a composite type, as if a single declaration was written:
int foo(void (*)(int), void (*)(int));
That should give you a bit of cud to chew on. ;) If you are really into this
sort of thing, comp.lang.c is a better newsgroup.
--
#exclude <windows.h>
------------------------------
** FOR YOUR REFERENCE **
The service address, to which questions about the list itself and requests
to be added to or deleted from it should be directed, is:
Internet: [EMAIL PROTECTED]
You can send mail to the entire list (and comp.os.linux.development.system) via:
Internet: [EMAIL PROTECTED]
Linux may be obtained via one of these FTP sites:
ftp.funet.fi pub/Linux
tsx-11.mit.edu pub/linux
sunsite.unc.edu pub/Linux
End of Linux-Development-System Digest
******************************