Think about pthread_create() the same way as fork() for threads, instead of processes. By default, pthread_create() creates a new thread tied to the thread which created it... You can create "detached" threads using the attribute argument:
Code:
extern void *thread_routine( void * );
pthread_attr_t attr;
pthread_t tid; // thread id;
pthread_attr_init( &attr );
pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_DETACHED );
pthread_create( &tid, &attr, thread_routine, NULL );
// now the new thread is running "detached".
pthread_attr_destroy( &attr ); // we don't need this anymore...
...
Another way to do it is calling pthread_detach(), inside the thread routine.
This way this new thread cannot be "joined" to the primary thread which created it. Why cannot be "joined"? Because "joinable" threads don't have their resources freed, automatically, if they aren't "joined"... Detached threads free their resources in thread termination.
pthread_join() is used a a barrier, where the current thread waits for the termination of the other running "joinable" threads.
Notice pthread_create() takes a pointer to a thread "descriptor" (where an ID for the new thread will be writen, like PID, for threads), a pointer to thread attributes (which you can tune using pthread_attr_* functions, or use the default attributes, passing NULL), a pointer to the routine that will run in this new thread and a pointer to the argument pthread_create will pass to this function.
pthread_join(), as I said before, will simply wait for thread termination and optionally, returns the pointer to the thread function return value, freeing thread resources in the process. So it needs only the thread "ID" and the pointer which will receive the result (or NULL if you don't care for results).