A stack is effectively an array -- it contains a bunch of words in contiguous memory, There is an important restriction -- it can only grow and shrink at one end (hence FILO -- First In Last Out) which is also LIFO.
Important difference from array too: Processor stack is logically split into Frames, and (unlike arrays), each frame can be a different size from any of the others.
Each frame contains what needs to be stored when you make a function call, including:
- The return address where the called function jumps, to continue in the calling function.
- Space to hold any return value.
- A copy of each parameter being passed to the called function.
- Copies of the CPU registers, so that the register optimisation in the separate functions don't interfere.
If you ever wondered how a function can recurse and yet use the same names for all its parameters and local variables in each level, the answer is that all of them have addresses relative to their current stack frame.
The stack frame structure is defined differently for each processor architecture, to adopt the most natural way of storing things. There isn't a "Linux" stack -- Intel and AMD and Sparc will all have their own definition. Remember you can download pre-compiled libraries that your local compiler has to know how to call from your own code.
A Stack is also a generic data structure in its own right. For example, if you are parsing the source of a language like C or SQL or XML that allows nested block constructs, then it is natural to make a stack of the blocks you are inside as you go. You wouldn't want to do that using the process stack: it's the thing you are parsing that has block structures, not your own code that needs to recurse.
The stack for each process is just a part of its user process memory. Typically, the user address space runs from -8MB to 0 to (say) 60MB. The stack starts at -16 and grows downwards (increasingly negative). Global and static memory assigned by the compiler is upwards from 0, and any heap allocation grows above the fixed memory. The code is somewhere separate (for protection reasons). It doesn't do the virtual storage system any harm to map your negative address range into paged memory.