http://bbs.chinaunix.net/thread-4187636-1-1.html
我做了两个实验:
第一个实验,创建一个本地文件,然后用5个线程对这个文件进行写入,结果前面的写入内容被后面的写入内容覆盖;对write函数加锁之后结果就正常了,就似乎验证了write函数是非线程安全的。
第二个实验,创建一个客户端的TCP socket,然后用5个线程对这个socket进行写入;服务器端把内容读取出来并打印,发现打印结果与客户端发送内容一致,没有出现异常,似乎说明write TCP socket是线程安全的。
我的问题是:
如果write不是线程安全的,为什么写TCP socket却正常,是否因为系统为socket操作加锁了?
实验代码如下
-
#include <unistd.h>
-
#include <errno.h>
-
#include <pthread.h>
-
-
#include <sys/socket.h>
-
#include <netinet/in.h>
-
#include <sys/types.h>
-
#include <sys/select.h>
-
#include <sys/stat.h>
-
#include <arpa/inet.h>
-
#include <fcntl.h>
-
-
#include <stdio.h>
-
#include <stdlib.h>
-
#include <string.h>
-
-
#define BUFF_SIZE 1024
-
-
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
-
-
struct ThreadArg
-
{
-
int id;
-
int fd;
-
};
-
-
void*
-
proc(void* arg)
-
{
-
struct ThreadArg* p_arg = (struct ThreadArg*) arg;
-
-
char msg[BUFF_SIZE];
-
int n_msg;
-
n_msg = snprintf(msg, BUFF_SIZE, "thread_%d\n", p_arg->id);
-
-
int i;
-
for (i = 0; i < 5; ++ i)
-
{
-
//pthread_mutex_lock(& mutex);
-
if (write(p_arg->fd, msg, n_msg) < 0)
-
perror("thread %d write fail");
-
//pthread_mutex_unlock(& mutex);
-
}
-
}
-
-
int
-
open_socket(char* ip)
-
{
-
int connfd;
-
struct sockaddr_in serv_addr;
-
-
if ( (connfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
-
return -1;
-
-
memset(&serv_addr, 0, sizeof(serv_addr));
-
serv_addr.sin_family = AF_INET;
-
serv_addr.sin_port = htons(9999);
-
inet_pton(AF_INET, ip, &serv_addr.sin_addr);
-
-
if ( connect(connfd, (struct sockaddr*) &serv_addr, sizeof(serv_addr)) == -1)
-
return -1;
-
-
return connfd;
-
}
-
-
int
-
open_file(char* file_name)
-
{
-
return open(file_name, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
-
}
-
-
int
-
main(int argc, char** argv)
-
{
-
int fd;
-
-
pthread_t tids[5];
-
struct ThreadArg targ[5];
-
-
//if ( (fd = open_socket("127.0.0.1")) < 0) // 实验二
-
// exit(1);
-
-
if ( (fd = open_file("data")) < 0) // 实验一
-
exit(1);
-
-
/* start child threads */
-
int i;
-
for (i = 0; i < 5; ++ i)
-
{
-
targ[i].id = i;
-
targ[i].fd = fd;
-
pthread_create(tids+i, NULL, proc, targ+i);
-
}
-
-
for (i = 0; i < 5; ++ i)
-
pthread_join(tids[i], NULL);
-
-
close(fd);
-
exit(0);
- }
-
#include <stdio.h>
-
#include <stdlib.h>
-
#include <string.h>
-
-
#include <sys/types.h>
-
#include <sys/socket.h>
-
#include <netinet/in.h>
-
#include <sys/epoll.h>
-
#include <fcntl.h>
-
-
#include <errno.h>
-
-
const int MAX_EVENTS = 1024;
-
const int BUFF_SIZE = 1024;
-
-
void err_quit(const char* msg) {
-
printf("%s, error code = %d\n", msg, errno);
-
exit(1);
-
}
-
-
void err_sys(const char* msg) {
-
printf("%s, error code = %d\n", msg, errno);
-
}
-
-
int create_and_bind(int port_no) {
-
int listen_fd;
-
struct sockaddr_in serv_addr;
-
-
if ( (listen_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
-
return -1;
-
-
memset(&serv_addr, 0, sizeof(serv_addr));
-
serv_addr.sin_family = AF_INET;
-
serv_addr.sin_addr.s_addr = INADDR_ANY;
-
serv_addr.sin_port = htons(port_no);
-
-
if ( bind(listen_fd, (struct sockaddr*) &serv_addr, sizeof(serv_addr)) < 0)
-
return -1;
-
-
return listen_fd;
-
}
-
-
int communicate(const int fd)
-
{
-
int n_msg = 9;
-
char msg[BUFF_SIZE];
-
-
int count = 0;
-
int n_read;
-
while ( (n_read = read(fd, msg, n_msg)) > 0)
-
{
-
msg[n_msg] = 0;
-
printf("%s", msg);
-
++ count;
-
}
-
-
printf("msg number = %d\n", count);
-
-
if (n_read < 0)
-
return -1;
-
return 0;
-
}
-
-
int main(int argc, char** argv) {
-
-
int listen_fd;
-
int conn_fd;
-
-
/* create and bind listening socket */
-
listen_fd = create_and_bind(9999);
-
if (listen_fd < 0)
-
err_quit("create and bind listening socket failed!");
-
-
/* listening */
-
listen(listen_fd, 100);
-
-
while (1) {
-
if ( (conn_fd = accept(listen_fd, NULL, NULL)) < 0)
-
err_sys("accept connection socket failed!");
-
else
-
if (communicate(conn_fd) < 0)
-
perror("read socket fail");
-
else
-
close(conn_fd);
-
}
-
-
close(listen_fd);
-
exit(0);
- }
printf()----stdout()
malloc-------内存分配表
free()--------内存分配表