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()--------内存分配表