/lib/i386-linux-gnu/libc.so.6
This is a 32-bit version of the library.
/lib/x86_64-linux-gnu/libc.so.6
This is a 64-bit version of the library.
Both are usually symbolic links to the actual library file, which will usually be named according to the glibc release number, for example libc-2.15.so
/usr/lib/x86_64-linux-gnu/libc.so
This is not a library, but a script linker file that references the aforementioned symbolic links.
Why do we need all this:
First, regardless of the version of libc installed, the linker will always look for libc.so , because the compiler driver will always go to the -lc option linker. The name libc remains unchanged and indicates the latest version of the library.
Symbols libc.so.6 are named after the name of the library, which more or less corresponds to the version of the ABI library. The executables associated with libc.so actually contain runtime dependencies on libc.so.6 .
If we imagine that someday a crude ABI-incompatible libc will be released, its soname can be called libc.so.7 , for example, and this version of coukld coexists with the old version of libc.so.6 , so the executable files related to otherwise, can coexist in the same system
And finally, the name libc-2.15.so refers to the libc release, when you install the new libc package, the name will change to libc-2.16.so . Provided that it is compatible with binary from the previous release, the link libc.so.6 will remain named this way and existing executables will continue to work.